bzoj 1497: [NOI2006]最大获利 最小割 最大权闭和子图

来源:互联网 发布:网络教育培训机构 编辑:程序博客网 时间:2024/06/03 06:42

→题目链接←

又是一道烂大街的模板题

蹭访问量...

居然因为一个字母而调了一下午...


从原点到每个用户群连边,流量为收益

每个用户群和两边的基站连边,边权为inf

每个基站再和汇点连边,流量为建这个基站的代价

ans=所有收益之和-最大流


非常弱的代码:

#include<iostream>#include<cstdio>#include<algorithm>#include<deque>#include<vector>#include<queue>#include<cstring>#define ll long long#define inf 0x3f3f3fusing namespace std;struct node{int to,num;}edge[440000];int n,m;int pn=1;vector<int>v[110000];int edgenum=0;int d[110000];void link(int x,int y,int z){node t;t.to=y;t.num=z;edge[edgenum]=t;v[x].push_back(edgenum);edgenum++;t.to=x;t.num=0;edge[edgenum]=t;v[y].push_back(edgenum);edgenum++;} bool bfs(){memset(d,-1,sizeof(d));d[0]=1;queue<int>q;q.push(0);while(!q.empty()){int t=q.front();q.pop();if(t==pn)continue;for(int i=0; i<v[t].size(); i++){int x=v[t][i];int to=edge[x].to;int num=edge[x].num;if(num==0 || d[to]!=-1)continue;d[to]=d[t]+1;q.push(to);}}if(d[pn]!=-1)return true;return false;}ll dfs(int x,int y){if(x==pn || y==0)return y;ll sum=0;for(int i=0; i<v[x].size(); i++){int j=v[x][i];int to=edge[j].to;int num=edge[j].num;if(num){if(d[to]!=d[x]+1)continue;ll k=dfs(to,min(num,y));if(k==0)continue;y-=k;sum+=k;edge[j].num-=k;edge[j^1].num+=k;if(y==0)break;}}if(sum==0)d[x]=-1;return sum;}long long ans=0;int main(){scanf("%d%d",&n,&m);for(int i=1; i<=n; i++){int x;scanf("%d",&x);link(i,n+m+1,x);}pn+=n+m;for(int i=1; i<=m; i++){int x,y,z;scanf("%d%d%d",&x,&y,&z);ans+=z;link(0,i+n,z);link(i+n,x,inf);link(i+n,y,inf);}while(bfs())ans-=dfs(0,inf);printf("%lld\n",ans);return 0;}


阅读全文
0 0