网络流建图,首先将所有价值加起来,用最小割考虑要删掉多少个价值:源点向每一个士兵连流量为x的边,士兵向汇点连流量为y的边,每一对关系间连流量为z的边,考虑有方程x1+y2+z=x2+y1+z=a+c,x1+x2=b+c,y1+y2=a+b,由于对称性(其实也不一定要对称),解得x1=x2=(b+c)/2,y1=y2=(a+b)/2,z=(a+c)/2-b,把边都乘以2用总价值减去最大流除以2就可以得到答案
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 505 4 #define ll long long 5 struct ji{ 6 int nex,to,len; 7 }edge[N*N]; 8 queue<int>q; 9 int E,n,m,x,y,a,b,c,d[N],head[N],work[N]; 10 void add(int x,int y,int z){ 11 edge[E].nex=head[x]; 12 edge[E].to=y; 13 edge[E].len=z; 14 head[x]=E++; 15 if (E&1)add(y,x,0); 16 } 17 bool bfs(){ 18 q.push(0); 19 for(int i=0;i<=n+1;i++)d[i]=-1; 20 d[0]=0; 21 while (!q.empty()){ 22 int k=q.front(); 23 q.pop(); 24 for(int i=head[k];i!=-1;i=edge[i].nex) 25 if ((edge[i].len)&&(d[edge[i].to]<0)){ 26 d[edge[i].to]=d[k]+1; 27 q.push(edge[i].to); 28 } 29 } 30 return d[n+1]>=0; 31 } 32 int dfs(int k,int s){ 33 if (k>n)return s; 34 int p; 35 for(int &i=work[k];i!=-1;i=edge[i].nex) 36 if ((edge[i].len)&&(d[edge[i].to]==d[k]+1)){ 37 p=dfs(edge[i].to,min(s,edge[i].len)); 38 if (p){ 39 edge[i].len-=p; 40 edge[i^1].len+=p; 41 return p; 42 } 43 } 44 return 0; 45 } 46 ll dinic(){ 47 int k=0; 48 ll ans=0; 49 while (bfs()){ 50 for(int i=0;i<=n+1;i++)work[i]=head[i]; 51 while (k=dfs(0,0x3f3f3f3f))ans+=k; 52 } 53 return ans; 54 } 55 int main(){ 56 while (scanf("%d%d",&n,&m)!=EOF){ 57 for(int i=0;i<=n+1;i++)head[i]=-1; 58 ll ans=E=0; 59 for(int i=1;i<=m;i++){ 60 scanf("%d%d%d%d%d",&x,&y,&a,&b,&c); 61 add(0,x,b+c); 62 add(0,y,b+c); 63 add(x,n+1,a+b); 64 add(y,n+1,a+b); 65 add(x,y,a+c-2*b); 66 add(y,x,a+c-2*b); 67 ans+=a+b+c; 68 } 69 printf("%lld\n",ans-dinic()/2); 70 } 71 }