POJ 2175

来源:互联网 发布:nerf淘宝 编辑:程序博客网 时间:2024/06/13 05:04

消圈定理:残留网络里如果存在负费用圈,那么当前流不是最小费用流。因为你绕着这个圈走一遍,费用更小了。


这道题是给你图之后,再给你一个分配方法,让你判断这个方法是不是最优的。

如果我们直接用走费用流的话会超时的,我们需要在他给的那个分配方法的基础上来做。

我们知道费用流问题是有反向边代表已经花费了的容量啥的,我们普通的建边时是设为0的,这次我们不设为0,

而是按照他给的方案来设置。就是说我们是从半途中开始搜寻最小费用流的。这样就不会超时了。

如果建好图,这个图存在负圈,也就是说明这不是最优的,因为我们走一遍负圈,我们的费用会减少。

那么i->j ++, j->i --。 最后我们输出我们的最优分配方法即可。


学习地址:

http://blog.csdn.net/u013761036/article/details/46363631

http://blog.csdn.net/onepiecehuiyu/article/details/8139377


ss -> i  流量0 费用0  
         //因为跑完之后前面肯定是流量都用没了
i -> ss 流量c ,费用0 
         //c是这个建筑有多少人,满流的正向0,反向满c
i -> j + n 流量INF-c 费用 w
         //w是i,j的距离+1,c是建筑里人数,本来是INF,跑完后是INF-c
j+n -> i  流量c ,费用w
         //如上
j+n -> tt 流量q,费用0,
         //q是建筑的容量剩余,就是所有的-当前用了的,当前用的综合自己算出来
tt -> j+n 流量p,费用0
         //p是当前这个避难所一共用了多少容量



  1. #include<queue>  
  2. #include<stdio.h>  
  3. #include<string.h>  
  4.   
  5. #define N_node 205  
  6. #define N_edge 30000  
  7. #define INF 100000000  
  8.   
  9. using namespace std;  
  10.   
  11. typedef struct  
  12. {  
  13.     int from ,to ,cost ,flow ,next;  
  14. }STAR;  
  15.   
  16. typedef struct  
  17. {  
  18.     int a ,b ,c;  
  19. }NODE;  
  20.   
  21. STAR E[N_edge];  
  22. int list[N_node] ,tot;  
  23. int C[N_node];//入队次数  
  24. int mer[N_node];//记录路径  
  25. int s_x[N_node] ,mark[N_node];  
  26. int now[N_node][N_node];  
  27. NODE A[N_node] ,B[N_node];  
  28.   
  29. void add(int a ,int b ,int c ,int d)  
  30. {  
  31.     E[++tot].from = a;  
  32.     E[tot].to = b;  
  33.     E[tot].cost = c;  
  34.     E[tot].flow = d;  
  35.     E[tot].next = list[a];  
  36.     list[a] = tot;  
  37. }  
  38.   
  39. int abss(int x)  
  40. {  
  41.     return x > 0 ? x : -x;  
  42. }  
  43.   
  44. bool Spfa(int s ,int n)  
  45. {  
  46.     for(int i = 0 ;i <= n ;i ++)  
  47.     s_x[i] = INF;  
  48.     memset(mark ,0 ,sizeof(mark));  
  49.     memset(C ,0 ,sizeof(C));  
  50.     queue<int>q; q.push(s);  
  51.     mark[s] = C[s] = 1 ,s_x[s] = 0;  
  52.     int xin ,tou;  
  53.     memset(mer ,255 ,sizeof(mer));  
  54.     while(!q.empty())  
  55.     {  
  56.         tou = q.front();  
  57.         q.pop();  
  58.         mark[tou] = 0;  
  59.         for(int k = list[tou] ;k ;k = E[k].next)  
  60.         {  
  61.             xin = E[k].to;  
  62.             if(s_x[xin] > s_x[tou] + E[k].cost && E[k].flow)  
  63.             {  
  64.                 s_x[xin] = s_x[tou] + E[k].cost;  
  65.                 mer[xin] = k;  
  66.                 if(!mark[xin])  
  67.                 {  
  68.                     mark[xin] = 1;  
  69.                     q.push(xin);  
  70.                     if(++C[xin] > n) return xin;  
  71.                 }  
  72.             }  
  73.         }  
  74.     }  
  75.     return 0;  
  76. }  
  77.   
  78. int main ()  
  79. {  
  80.     int n ,m ,i ,j;  
  81.     int st[N_node];  
  82.     while(~scanf("%d %d" ,&n ,&m))  
  83.     {  
  84.         for(i = 1 ;i <= n ;i++)  
  85.         scanf("%d %d %d" ,&A[i].a ,&A[i].b ,&A[i].c);  
  86.         for(i = 1 ;i <= m ;i ++)  
  87.         scanf("%d %d %d" ,&B[i].a ,&B[i].b ,&B[i].c);  
  88.         memset(st ,0 ,sizeof(st));  
  89.         for(i = 1 ;i <= n ;i ++)  
  90.         for(j = 1 ;j <= m ;j ++)  
  91.         {  
  92.             scanf("%d" ,&now[i][j]);  
  93.             st[j] += now[i][j];  
  94.         }  
  95.         memset(list ,0 ,sizeof(list));  
  96.         tot = 1;  
  97.         int ss = 0 ,tt = n + m + 1;  
  98.         for(i = 1 ;i <= n ;i ++)  
  99.         add(ss ,i ,0 ,0),add(i ,ss ,0 ,A[i].c);  
  100.         for(i = 1 ;i <= m ;i ++)  
  101.         add(i + n ,tt ,0 ,B[i].c - st[i]) ,add(tt ,i + n ,0 ,st[i]);  
  102.         for(i = 1 ;i <= n ;i ++)  
  103.         for(j = 1 ;j <= m ;j ++)  
  104.         {  
  105.             add(i ,j + n ,abss(A[i].a-B[j].a)+abss(A[i].b - B[j].b) + 1 ,INF - now[i][j]);  
  106.             add(j + n ,i ,-(abss(A[i].a-B[j].a)+abss(A[i].b - B[j].b) + 1) ,now[i][j]);  
  107.         }  
  108.         int x = Spfa(tt ,tt);  
  109.         if(!x)  
  110.         {  
  111.             printf("OPTIMAL\n");  
  112.             continue;  
  113.         }  
  114.         printf("SUBOPTIMAL\n");  
  115.         memset(mark ,0 ,sizeof(mark));  
  116.         i = mer[x];  
  117.         while(1)//找到一个肯定在环上的点  
  118.         {  
  119.             x = E[i].to;  
  120.             if(mark[x]) break;  
  121.             mark[x] = 1;  
  122.             i = mer[E[i].from];  
  123.         }  
  124.         memset(mark ,0 ,sizeof(mark));  
  125.         for(i = mer[x] ;i + 1 ;i = mer[E[i].from])  
  126.         {  
  127.             int a = E[i].from ,b = E[i].to;  
  128.             if(a >= 1 && a <= n && b >= n + 1 && b <= n + m)  
  129.             now[a][b-n] ++;  
  130.             if(a >= n + 1 && a <= n + m && b >= 1 && b <= n)  
  131.             now[b][a-n] --;  
  132.             if(mark[a] && mark[b]) break;  
  133.             mark[a] = mark[b] = 1;  
  134.         }  
  135.         for(i = 1 ;i <= n ;i ++)  
  136.         for(j = 1 ;j <= m ;j ++)  
  137.         if(j == m) printf("%d\n" ,now[i][j]);  
  138.         else printf("%d " ,now[i][j]);  
  139.     }  
  140.     return 0;  
  141.   
  142. }  

原创粉丝点击