HDU 3491 Thieves 【拆點+最大流】

【題目地址】

http://acm.hdu.edu.cn/showproblem.php?pid=3491

【題目大意】

有n個城市和m條道路(雙向),一夥thieves準備從S城出發到H城盜竊,The  brave,  brilliant,  bright  police(囧!!)爲了將這夥thieves抓住,需要在這n個城市中的每一個城市安排一定數量的police(已知條件)。但police不希望在S城或H城邂逅thieves。

求總共需要的最少police數。

【解題思路】

把城市作爲點拆開(把城市 i 拆成cap數組中的cap[i][i+n].其中i作爲城市i的入,i+n作爲城市i的出),原來的道路仍然作爲邊,但是邊權是無窮大. 只要注意到BFS的時候 起點/終點是不需要拆的.(在cap[][]數組中就直接把起點/終點的入和出之間的邊權賦值爲0,使得BFS的時候不走起點/終點,實際上就相當於沒有把起點/終點拆開.程序中的處理方法就是 cap[s][s+n] = 0;/cap[e][e+n] = 0;)

PS(與本題無關):HDU 3549(最大流)WA了n次,才知道兩點之間可能有多條道路,cap[][]爲邊權之和。

題目n<=100,m<=10000,建議用SAP或Dinic求最大流,時間複雜度爲O(V^2 * E)。

本題數據較弱,下面是O(V*E^2)的樸素層次圖算法(實際上就是BFS。。(*^__^*) )代碼:

【代碼】

隱藏行號 複製代碼 C/C++
  1. #include<cstdio>
    
  2. #include<cstring>
    
  3. #define inf 2147483647
    
  4. #define maxn 201
    
  5. int cap[maxn][maxn],que[maxn],pre[maxn],vis[maxn];
    
  6. int s,t,n,m,h;
    
  7. bool bfs()
    
  8. {
    
  9.     int i,j,l=0,r=0;
    
  10.     que[r++]=s;
    
  11.     memset(vis,0,sizeof(vis));
    
  12.     while(l<r)
    
  13.     {
    
  14.         j=que[l++];
    
  15.         for(i=1;i<=2*n;i++)
    
  16.             if(!vis[i]&&cap[j][i]>0)
    
  17.             {
    
  18.                 vis[i]=1;
    
  19.                 pre[i]=j;
    
  20.                 if(i==t) 
    
  21.                     return true;
    
  22.                 que[r++]=i;
    
  23.             }
    
  24.     }
    
  25.     return false;
    
  26. }
    
  27. int maxflow()
    
  28. {
    
  29.     int flow=0,i,min;
    
  30.     while(bfs())
    
  31.     {
    
  32.         for(i=t,min=inf;i!=s;i=pre[i])
    
  33.             if(cap[pre[i]][i]<min)
    
  34.                 min=cap[pre[i]][i];
    
  35.             flow+=min;
    
  36.             for(i=t; i!=s;i=pre[i])
    
  37.             {
    
  38.                 cap[pre[i]][i]-=min;
    
  39.                 cap[i][pre[i]]+=min;
    
  40.             }
    
  41.     }
    
  42.     return flow;
    
  43. }
    
  44. int main()
    
  45. {
    
  46.     int T,x,y,i;
    
  47.     scanf("%d", &T);
    
  48.     while(T--)
    
  49.     {
    
  50.         memset(cap,0,sizeof(cap));
    
  51.         scanf("%d%d%d%d",&n,&m,&s,&h);
    
  52.         for(i=1;i<=n;i++)
    
  53.             scanf("%d",&cap[i][i+n]);
    
  54.         s=s+n;t=h;
    
  55.         cap[h][h+n]=0;
    
  56.         cap[s][s+n]=0;
    
  57.         for(i=1;i<=m;i++)
    
  58.         {
    
  59.             scanf("%d%d",&x,&y);
    
  60.             cap[x+n][y]=inf;
    
  61.             cap[y+n][x]=inf;
    
  62.         }
    
  63.         printf("%d/n",maxflow());
    
  64.     }
    
  65.     return 0;
    
  66. }
    
  67. 
    

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章