Harmonious Army
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 1539 Accepted Submission(s): 557
Problem Description
Now, Bob is playing an interesting game in which he is a general of a harmonious army. There are n soldiers in this army. Each soldier should be in one of the two occupations, Mage or Warrior. There are m pairs of soldiers having combination ability. There are three kinds of combination ability. If the two soldiers in a pair are both Warriors, the army power would be increased by a. If the two soldiers in a pair are both Mages, the army power would be increased by c. Otherwise the army power would be increased by b, and b=a/4+c/3, guaranteed that 4|a and 3|c. Your task is to output the maximum power Bob can increase by arranging the soldiers’ occupations.
Note that the symbol a|b means that a divides b, e.g. , 3|12 and 8|24.
Input
There are multiple test cases.
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.
Output
For each test case, output one line containing the maximum power Bob can increase by arranging the soldiers’ occupations.
Sample Input
3 2
1 2 8 3 3
2 3 4 3 6
Sample Output
12
Source
2019 Multi-University Training Contest 2
对于每个士兵非黑即白(也就是要么法师,要么战士),但是这道题和其他不一样,这道题有三种价值,而且只有组合才会产生价值。
考虑最小割建图:也就是考虑士兵的集合划分,对于两边的划分,分别算出割掉的价值即可,然后最小割,用所有价值减去最小割即为答案。
AC代码:
#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1010,M=1e6+10;
int n,m,h[N],s,t,res;
int head[N],nex[M],to[M],w[M],tot;
inline void ade(int a,int b,int c){
to[++tot]=b; nex[tot]=head[a]; w[tot]=c; head[a]=tot;
}
inline void add(int a,int b,int c){
ade(a,b,c); ade(b,a,0);
}
inline void init(){
res=0; memset(head,0,sizeof head); tot=1; t=n+1;
}
inline int bfs(){
queue<int> q; q.push(s); memset(h,0,sizeof h); h[s]=1;
while(q.size()){
int u=q.front(); q.pop();
for(int i=head[u];i;i=nex[i]){
if(!h[to[i]]&&w[i]){
h[to[i]]=h[u]+1; q.push(to[i]);
}
}
}
return h[t];
}
int dfs(int x,int f){
if(x==t) return f; int fl=0;
for(int i=head[x];i&&f;i=nex[i]){
if(h[to[i]]==h[x]+1&&w[i]){
int mi=dfs(to[i],min(w[i],f));
w[i]-=mi; w[i^1]+=mi; fl+=mi; f-=mi;
}
}
if(!fl) h[x]=-1;
return fl;
}
int dinic(){
int res=0;
while(bfs()) res+=dfs(s,0x3f3f3f3f);
return res;
}
signed main(){
while(~scanf("%lld %lld",&n,&m)){
init();
for(int i=1;i<=m;i++){
int u,v,a,b,c; scanf("%lld %lld %lld %lld %lld",&u,&v,&a,&b,&c);
a*=2; b*=2; c*=2; res+=(a+b+c);
add(s,u,5*a/8+c/6); add(s,v,5*a/8+c/6); add(u,v,a/4+c/6);
add(v,u,a/4+c/6); add(u,t,a/8+2*c/3); add(v,t,a/8+2*c/3);
}
printf("%lld\n",(res-dinic())/2);
}
return 0;
}