Harmonious Army
Time limit: 1 Sec Memory Limit: 128 MBTitle Description
Note that the symbol a|b means that a divides b, e.g. , 3|12 and 8|24.
Entry
Each case starts with a line containing two positive integers n(n≤500) and m(m≤104).
In the following m lines, each line contains five positive integers u,v,a,b,c (1≤u,v≤n,u≠v,1≤a,c≤4×106,b=a/4+c/3), denoting soldiers u and v have combination ability, guaranteed that the pair (u,v) would not appear more than once.
It is guaranteed that the sum of n in all test cases is no larger than 5×103, and the sum of m in all test cases is no larger than 5×104.
Export
Sample input
3 2
1 2 8 3 3
2 3 4 3 6
Sample Output
12
Meaning of the questions: n soldiers to arrange two professions, there are m relations, relations with the contribution of the professional relationship between the two sides about the soldiers, and seeking the maximum contribution.
Figure minimal cut build a good question, Mark it. Ideas Reference Solution:
Establish a point x for each soldier, the source point x s even an edge to the Meeting Point t even an edge, respectively, choose two professions, then you can add all of the first contribution, by two points with minimal relations modeling cut, as shown in FIG.
Provided three kinds of contribution to a side A; B; C, the following equation can be obtained:
A + B = A + B (X, Y are selected from Mage)
c + d = C + B (x, y are selected Warrior)
a + d + e = A + C (x is selected from Mage, y is selected from Warrior)
b + c + e = A + C (x is selected from Warrior, y is selected from Mage)
A set of solutions can be obtained a = b = (A + B) / 2, c = d = (C + B) / 2, e = -B + (A + C) / 2, then the two points are related to all Figure merger, minus the minimum figure can be cut with all contributions.
#include<bits/stdc++.h> #define N 505 using namespace std; typedef struct { int to,next; long long flow; }ss; ss edg[N*N]; int now_edge=0,s,t; int head[N]; void addedge(int u,int v,long long flow) { edg[now_edge]=(ss){v,head[u],flow}; head[u]=now_edge++; edg[now_edge]=(ss){u,head[v],0}; head[v]=now_edge++; } int dis[N]; bool bfs() { memset(dis,0,sizeof(dis)); queue<int>q; q.push(s); dis[s]=1; while(!q.empty()) { int now=q.front(); q.pop(); for(int i=head[now];i!=-1;i=edg[i].next) { ss &e=edg[i]; if(e.flow>0&&dis[e.to]==0) { dis[e.to]=dis[now]+1; q.push(e.to); } } } if(dis[t]==0)return 0; return 1; } int current[N]; long long dfs(int x,long long maxflow) { if(x==t)return maxflow; // printf("%d %lld\n",x,maxflow); for(int i=current[x];i!=-1;i=edg[i].next) { current[x]=i; ss &e=edg[i]; if(e.flow>0&&dis[e.to]==dis[x]+1) { long long flow=dfs(e.to,min(maxflow,e.flow)); if(flow!=0) { e.flow-=flow; edg[i^1].flow+=flow; return flow; } } } return 0; } long long dinic() { long long ans=0,flow; while(bfs()) { for(int i=0;i<N;i++)current[i]=head[i]; while(flow=dfs(s,LLONG_MAX/2))ans+=flow; } return ans; } void init() { for(int i=0;i<N;i++)head[i]=-1; now_edge=0; } int Map[N][N]; int main() { int n,m; while(scanf("%d %d",&n,&m)==2) { init(); for(int i=0;i<=n+2;i++) for(int j=0;j<=n+2;j++)Map[i][j]=0; long long ans=0; s=n+1; t=s+1; while(m--) { int u,v,a,b,c; scanf("%d %d %d %d %d",&u,&v,&a,&b,&c); ans+=a+b+c; Map[s][u]+=a+b; Map[s][v]+=a+b; Map[u][t]+=c+b; Map[v][t]+=c+b; Map[u][v]+=a+c-2*b; Map[v][u]+=a+c-2*b; } for(int i=1;i<=n+2;i++) for(int j=1;j<=n+2;j++)if(Map[i][j])addedge(i,j,Map[i][j]); printf("%lld\n",ans-dinic()/2); } return 0; }