为了博多
Description
做了个噩梦,梦见我的 n 把刀到60级会二次变身,变成一个 对推6图有xi点贡献,刷大阪城有yi点贡献 的刀,于是要把刀分成两队一队刷大阪城另一队推6图 。
但是有m对兄弟刀在同一队会有特殊的buff加成,加成值为wi,问怎样分队收益最大,最大值是多少。
Input
第一行两个整数n(刀的数目)(0<=n<=20000),m(兄弟刀的对数)(0<=m<=200000)
接下来n行,每行两个整数xi,yi,分别表示第i把刀对推6图的贡献xi和对刷大阪城的贡献yi。
接下来m行,每行三个整数u,v,wi,分别表示第u把刀和第v把刀是兄弟刀,在一队能产生wi的buff值。
Output
一行一个数字,表示最大收益
Sample Input
3 1
1 10
2 10
10 3
2 3 1000
Sample Output
1023
题解:
不同寻常的思维:
用的是最大权闭合子图的思想,直接用总收益减掉不合法的,建边比较巧妙.
对于每一个点(S,i,xi) (i,T,yi)
对于每一组关联:(x,y,wi) 建双向边
哪一个损失小就割在哪条边
答案就是sum-最小割
1 #include <algorithm> 2 #include <iostream> 3 #include <cstdlib> 4 #include <cstring> 5 #include <cstdio> 6 #include <cmath> 7 #define RG register 8 using namespace std; 9 typedef long long ll; 10 const int N=20005,M=200005,INF=2e9; 11 int head[N],num=1; 12 struct Lin{ 13 int next,to,dis; 14 }a[(M+N)<<2]; 15 void init(int x,int y,int z){ 16 a[++num].next=head[x];a[num].to=y;a[num].dis=z;head[x]=num; 17 } 18 void addedge(int x,int y,int z){ 19 init(x,y,z);init(y,x,0); 20 } 21 int gi(){ 22 int str=0;char ch=getchar(); 23 while(ch>'9' || ch<'0')ch=getchar(); 24 while(ch>='0' && ch<='9')str=(str<<1)+(str<<3)+ch-48,ch=getchar(); 25 return str; 26 } 27 int n,m,S=0,T,q[N],dep[N]; 28 bool bfs(){ 29 memset(dep,0,sizeof(dep)); 30 RG int x,u,t=0,sum=1; 31 q[1]=S;dep[S]=1; 32 while(t!=sum){ 33 x=q[++t]; 34 for(RG int i=head[x];i;i=a[i].next){ 35 u=a[i].to; 36 if(dep[u] || a[i].dis<=0)continue; 37 dep[u]=dep[x]+1;q[++sum]=u; 38 } 39 } 40 return dep[T]; 41 } 42 int dfs(int x,int flow){ 43 if(x==T || !flow)return flow; 44 int tot=0;int tmp,u; 45 for(RG int i=head[x];i;i=a[i].next){ 46 u=a[i].to; 47 if(dep[u]!=dep[x]+1 || a[i].dis<=0)continue; 48 tmp=dfs(u,min(flow,a[i].dis)); 49 tot+=tmp;flow-=tmp; 50 a[i].dis-=tmp;a[i^1].dis+=tmp; 51 if(!flow)break; 52 } 53 if(!tot)dep[x]=0; 54 return tot; 55 } 56 int maxflow(){ 57 int tot=0,tmp; 58 while(bfs()){ 59 tmp=dfs(S,INF); 60 while(tmp)tot+=tmp,tmp=dfs(S,INF); 61 } 62 return tot; 63 } 64 void work(){ 65 n=gi();m=gi();T=n+1; 66 int x,y,z;ll ans=0; 67 for(RG int i=1;i<=n;i++){ 68 x=gi();y=gi(); 69 addedge(S,i,x);addedge(i,T,y); 70 ans+=x+y; 71 } 72 for(RG int i=1;i<=m;i++){ 73 x=gi();y=gi();z=gi(); 74 addedge(x,y,z);addedge(y,x,z); 75 ans+=z; 76 } 77 ans=ans-maxflow(); 78 printf("%lld\n",ans); 79 } 80 int main() 81 { 82 freopen("hakata.in","r",stdin); 83 freopen("hakata.out","w",stdout); 84 work(); 85 return 0; 86 }