好题,详细题解在这里http://blog.csdn.net/weiguang_123/article/details/8077385

这里回顾一下:

当i和j都在一个集合里会产生新的收益,是经典题直接建

当i和j不在同一个集合产生新的收益,需要点是二分图XY并把X或Y点集s-t反建

这里是类似的(以前的总结:http://www.cnblogs.com/phile/p/4473226.html)

  1 #include<bits/stdc++.h>
  2 
  3 using namespace std;
  4 typedef long long ll;
  5 const int inf=1e9+7;
  6 struct way{int po,flow,next;} e[2400010];
  7 int t,n,p[1010],pre[1010],numh[1010],cur[1010],h[1010],d[1010],m,len;
  8 
  9 void add(int x,int y,int f)
 10 {
 11      e[++len].po=y;
 12      e[len].flow=f;
 13      e[len].next=p[x];
 14      p[x]=len;
 15 }
 16 void build(int x, int y, int f)
 17 {
 18      add(x,y,f);
 19      add(y,x,0);
 20 }
 21 ll sap()
 22 {
 23     memset(numh,0,sizeof(numh));
 24     memset(h,0,sizeof(h));
 25     numh[0]=t+1;
 26     for (int i=0; i<=t; i++) cur[i]=p[i];
 27     int j,u=0,neck=inf; ll s=0;
 28     while (h[0]<t+1)
 29     {
 30           d[u]=neck;
 31           bool ch=1;
 32           for (int i=cur[u]; i!=-1; i=e[i].next)
 33           {
 34               j=e[i].po;
 35               if (e[i].flow>0&&h[u]==h[j]+1)
 36               {
 37                  neck=min(neck,e[i].flow);
 38                  cur[u]=i;
 39                  pre[j]=u;  u=j;
 40                  if (u==t)
 41                  {
 42                     s+=neck;
 43                     while (u)
 44                     {
 45                           u=pre[u];
 46                           j=cur[u];
 47                           e[j].flow-=neck;
 48                           e[j^1].flow+=neck;
 49                     }
 50                     neck=inf;
 51                  }
 52                  ch=0;
 53                  break;
 54               }
 55           }
 56           if (ch)
 57           {
 58              if (--numh[h[u]]==0) return s;
 59              int q=-1,tmp=t;
 60              for (int i=p[u]; i!=-1; i=e[i].next)
 61              {
 62                  j=e[i].po;
 63                  if (e[i].flow&&h[j]<tmp)
 64                  {
 65                     tmp=h[j];
 66                     q=i;
 67                  }
 68              }
 69              cur[u]=q; h[u]=tmp+1;
 70              numh[h[u]]++;
 71              if (u)
 72              {
 73                 u=pre[u];
 74                 neck=d[u];
 75              }
 76           }
 77     }
 78     return s;
 79 }
 80 
 81 int main()
 82 {
 83     int cas;
 84     scanf("%d",&cas);
 85     while (cas--)
 86     {
 87         len=-1;
 88         memset(p,255,sizeof(p));
 89         scanf("%d",&n);
 90         ll ans=0;
 91         for (int i=1; i<=n; i++)
 92         {
 93             int s=0;
 94             for (int j=1; j<=n; j++)
 95             {
 96                 int x;
 97                 scanf("%d",&x);
 98                 s+=x; ans+=x;
 99                 build(i,j,x);
100             }
101             build(0,i,s);
102         }
103         t=n+1;
104         for (int i=1; i<=n; i++)
105         {
106             int x;
107             scanf("%d",&x);
108             build(i,t,x);
109         }
110         printf("%lld\n",ans-sap());
111     }
112 }
View Code

 

posted on 2017-03-26 16:45  acphile  阅读(255)  评论(0编辑  收藏  举报