ural 1277. Cops and Thieves【最小割】

来源:互联网 发布:ubuntu php sqlite3 编辑:程序博客网 时间:2024/04/30 04:04
 

ural 1277. Cops and Thieves【最小割】

分类: 【图论专辑】 210人阅读 评论(2) 收藏 举报

              /*   小偷要从S城市到T城市偷东西,每个城市需要不同数量的警察来看守,现在给出警察数量,看能不能成功阻止小偷
               *   题意即是求最小割,但是由于给出的是每个点的容量,所以需要将每个点拆为两个点,之间连边,容量为点的容量,
               *   两个城市如果相连则容量置为无穷大。然后求最大流看是否大于已有警察数。拆点的时候可以将点i拆为2*i-1和2*i
               *   这个题最后一组数据源点和汇点是一个点,很变态,需要特别考虑。。。@@
               */

 

[cpp] view plaincopy
  1. #include <cstdio>  
  2. #include <cstring>  
  3. #define FOR(a,b) for(int i = a; i<= b; ++i)  
  4. #define INF 0x1f1f1f1f  
  5. #define MAXN 250  
  6. using namespace std;  
  7. int n,m,src,sink,num;  
  8. int cap[MAXN][MAXN],f[MAXN][MAXN],level[MAXN],q[MAXN];  
  9. inline bool dinic_bfs(){  
  10.     int queue[MAXN];  
  11.     memset(level,-1,sizeof(level));  
  12.     int head = 0,tail = 0;  
  13.     queue[tail++] = src;  
  14.     level[src] = 0;  
  15.     while(tail > head){  
  16.         int tep = queue[head++];  
  17.         for(int i = 1;i <= n; ++i){  
  18.             if(level[i] == -1 && cap[tep][i] > f[tep][i]){  
  19.                 level[i] = level[tep] + 1;  
  20.                 queue[tail++] = i;  
  21.             }  
  22.         }  
  23.     }  
  24.     return level[sink] != -1;  
  25. }  
  26. inline int dinic(){  
  27.     int cur,k,m,tail,maxflow = 0, *stack = q;  
  28.     while(dinic_bfs()){  
  29.         tail = 0;  
  30.         stack[tail++] = src;  
  31.         while(tail){  
  32.             cur = stack[tail-1];  
  33.             if(cur == sink){  
  34.                 m = INF;  
  35.                 for(int i = 1;i < tail; ++i){  
  36.                     if(m > cap[stack[i-1]][stack[i]]-f[stack[i-1]][stack[i]]){  
  37.                         m = cap[stack[i-1]][stack[i]]-f[stack[i-1]][stack[i]];  
  38.                         k = i;  
  39.                     }  
  40.                 }  
  41.                 maxflow += m;  
  42.                 for(int i = 1;i < tail; ++i){  
  43.                     f[stack[i-1]][stack[i]] += m;  
  44.                     f[stack[i]][stack[i-1]] -= m;  
  45.                 }  
  46.                 tail = k;  
  47.             }  
  48.             else{  
  49.                 int i;  
  50.                 for(i = 1;i <= n; ++i){  
  51.                     if(level[i] == level[cur] + 1 && cap[cur][i] > f[cur][i]){  
  52.                         stack[tail++] = i;  
  53.                         break;  
  54.                     }  
  55.                 }  
  56.                 if(i == n+1){  
  57.                     level[cur] = -1;  
  58.                     --tail;  
  59.                 }  
  60.             }  
  61.         }  
  62.     }  
  63.     return maxflow;  
  64. }  
  65. int main()  
  66. {  
  67.     while(scanf("%d",&num) != EOF){  
  68.         int k;  
  69.         scanf("%d%d%d%d",&n,&m,&src,&sink);  
  70.         memset(cap,0,sizeof(cap));  
  71.         memset(f,0,sizeof(f));  
  72.         for(int i = 1;i <= n; ++i){  
  73.             scanf("%d",&k);  
  74.             cap[2*i-1][2*i] = k;         // 将一个点拆为两个点,容量为点的容量  
  75.             cap[2*i][2*i-1] = k;  
  76.         }  
  77.         while(m--){  
  78.             int u,v;  
  79.             scanf("%d%d",&u,&v);  
  80.             cap[2*u][2*v-1] = INF;  
  81.             cap[2*v][2*u-1] = INF;  
  82.         }  
  83.         n = 2*n; src = 2*src; sink = 2*sink - 1;  
  84.         int ans = dinic();    
  85.         if(ans > num || sink+1 == src)//如果最大流大于警察数或者源点汇点是一个点  
  86.             printf("NO/n");  
  87.         else printf("YES/n");  
  88.     }  
  89. }  

原创粉丝点击