【網路流-最大權閉合子圖】CF1082G Petya and Graph
阿新 • • 發佈:2018-12-03
【題目】
原題地址
給定一幅圖,求子圖的最大權值,權值定義為邊權和-點權和。
,邊權
【解題思路】
十分經典的最小割建圖。
對於每個點
,連
,對於一條邊
,連
用所有邊權和減去最小割即可。
考慮為什麼是對的?實際上就相當於對一條邊限制了選擇它的兩個端點得到邊權,或者放棄邊權。
【參考程式碼】
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e3+10,INF=0x3f3f3f3f;
int n,m,tot,S,T;
int head[N],cur[N],dis[N];
ll ans;
queue<int>q;
int read()
{
int ret=0;char c=getchar();
while(!isdigit(c)) c=getchar();
while(isdigit(c)) ret=ret*10+(c^48),c=getchar();
return ret;
}
struct Tway{int v,w,nex;}e[N<<3];
void add(int u,int v,int w)
{
e[++tot]=(Tway){v,w,head[u]};head[u]=tot;
e[++tot]=(Tway){u,0,head[v]};head[v]=tot;
}
bool bfs()
{
memcpy(cur,head,sizeof(head));
memset(dis,-1,sizeof(dis));
while(!q.empty()) q.pop();
q.push(S);dis[S]=0;
while(!q.empty())
{
int x=q.front();q.pop();
for(int i=head[x];i;i=e[i].nex)
{
int v=e[i].v;
if(!~dis[v] && e[i].w) dis[v]=dis[x]+1,q.push(v);
}
}
return ~dis[T];
}
int dfs(int x,int flow)
{
if(x==T || !flow) return flow;
int f,used=0;
for(int &i=cur[x];i;i=e[i].nex)
{
int v=e[i].v;
if(dis[v]!=dis[x]+1 || !(f=dfs(v,min(flow-used,e[i].w)))) continue;
e[i].w-=f;e[i^1].w+=f;used+=f;
if(used==flow) break;
}
return used;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("CF1082G.in","r",stdin);
freopen("CF1082G.out","w",stdout);
#endif
n=read();m=read();S=0;T=n+m+1;tot=1;
for(int i=1;i<=n;++i) add(S,i,read());
for(int i=1;i<=m;++i)
{
int u=read(),v=read(),w=read();
add(u,i+n,INF);add(v,i+n,INF);add(i+n,T,w);
ans+=w;
}
while(bfs()) ans-=dfs(S,INF);
printf("%lld\n",ans);
return 0;
}
【總結】
水過了一天。