标签:push 最小 做了 整数 iostream sub 收入 queue ini
做了个噩梦,梦见我的 n 把刀到60级会二次变身,变成一个 对推6图有xi点贡献,刷大阪城有yi点贡献 的刀,于是要把刀分成两队一队刷大阪城另一队推6图 。
但是有m对兄弟刀在同一队会有特殊的buff加成,加成值为wi,问怎样分队收益最大,最大值是多少。
第一行两个整数n(刀的数目)(0<=n<=20000),m(兄弟刀的对数)(0<=m<=200000)
接下来n行,每行两个整数xi,yi,分别表示第i把刀对推6图的贡献xi和对刷大阪城的贡献yi。
接下来m行,每行三个整数u,v,wi,分别表示第u把刀和第v把刀是兄弟刀,在一队能产生wi的buff值。
一行一个数字,表示最大收益
3 1
1 10
2 10
10 3
2 3 1000
1023
#include<iostream> #include<stdio.h> #include<stdlib.h> #include<algorithm> #include<queue> #include<cstring> const int MAXN=2000100; using namespace std; struct edge{ int first; int next; int cap; int to; }a[MAXN]; int dis[MAXN],n,m,sum=0,num=1; int s,t; queue<int> q; void addedge(int from,int to,int cap){ a[++num].to=to; a[num].cap=cap; a[num].next=a[from].first; a[from].first=num; } void link(int x,int y,int cap){ addedge(x,y,cap),addedge(y,x,0); } bool bfs(){ while(!q.empty()) q.pop(); memset(dis,0,sizeof(dis)); dis[s]=1;q.push(s); while(!q.empty()){ int now=q.front(); q.pop(); for(int i=a[now].first;i;i=a[i].next){ int to=a[i].to; if(dis[to]==0&&a[i].cap>0){ dis[to]=dis[now]+1; q.push(to); if(to==t) return 1; } } } return 0; } int dfs(int now,int flow){ if(now==t) return flow; int tag=0; for(int i=a[now].first;i;i=a[i].next){ int to=a[i].to; if(dis[to]==dis[now]+1&&a[i].cap>0){ int minn=dfs(to,min(a[i].cap,flow-tag)); a[i].cap-=minn; a[i^1].cap+=minn; tag+=minn; if(tag==flow) return tag; } } return tag; } int dinic(){ int max_flow=0; while(bfs()) max_flow+=dfs(s,1<<30); return max_flow; } int main(){ scanf("%d%d",&n,&m);s=0,t=n+1; for(int i=1;i<=n;i++){ int x,y; scanf("%d%d",&x,&y); sum+=(x+y); link(0,i,x),link(i,t,y); } for(int i=1;i<=m;i++){ int x,y,z; scanf("%d%d%d",&x,&y,&z); link(x,y,z);link(y,x,z); sum+=z; } printf("%d",sum-dinic()); return 0; }
标签:push 最小 做了 整数 iostream sub 收入 queue ini
原文地址:http://www.cnblogs.com/renjianshige/p/7224664.html