您的位置:首页 > 理论基础 > 计算机网络

【BZOJ1497】【codevs1789】最大获利,网络流之最大权闭合子图

2016-05-04 07:16 537 查看
传送门1

传送门2

写在前面:困啊困╯﹏╰

思路:建立中转站的点和用户群的点,s连中转站,流量为其建立成本,用户群点连t,流量为其获利,中转站与其对应的用户群连流量为inf的边,直接跑最大流就可以了

注意:无

#include<bits/stdc++.h>
#define inf 0x7fffff
using namespace std;
int n,m,s,t,tot=1,ans;
int first[55010],dis[55010],cur[55010];
struct edge
{
int u,v,w,next;
}e[320000];
queue<int>q;
int in()
{
int t=0;char ch=getchar();
while (!isdigit(ch)) ch=getchar();
while (isdigit(ch)) t=(t<<3)+(t<<1)+ch-48,ch=getchar();
return t;
}
void add(int x,int y,int z) {e[++tot]=(edge){x,y,z,first[x]};first[x]=tot;}
bool bfs()
{
memset(dis,0,sizeof(dis));
q.push(s);dis[s]=1;
while (!q.empty())
{
int k=q.front();q.pop();
for (int i=first[k];i;i=e[i].next)
if (e[i].w&&!dis[e[i].v])
q.push(e[i].v),dis[e[i].v]=dis[k]+1;
}
if (dis[t])
for (int i=s;i<=t;i++) cur[i]=first[i];
return dis[t];
}
int dfs(int x,int maxn)
{
if (x==t) return maxn;
int used=0;
for(int i=cur[x];i;i=e[i].next)
if (dis[e[i].v]==dis[x]+1)
{
int k=dfs(e[i].v,min(maxn-used,e[i].w));
e[i].w-=k;e[i^1].w+=k;
if (e[i].w) cur[x]=i;
used+=k;
if (used==maxn) return maxn;
}
if (!used) dis[x]=0;
return used;
}
main()
{
n=in();m=in();
t=n+m+1;
int x,y,z;
for (int i=1;i<=n;i++) add(s,i,in()),add(i,s,0);
for (int i=1;i<=m;i++)
x=in(),y=in(),z=in(),ans+=z,
add(x,i+n,inf),add(i+n,x,0),
add(y,i+n,inf),add(i+n,y,0),
add(i+n,t,z),add(t,i+n,0);
while (bfs()) ans-=dfs(s,inf);
printf("%d",ans);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: