[CF1082G]Petya and Graph:最小割

分析

发这篇博客的目的就是要让你们知道博主到底有多菜。

类似于[NOI2006]最大获利。(明明就是一模一样好吧!)

不知道怎么了,半秒就想到用网络流,却没想出怎么建图。

连这么简单的题都没做出来,我实在是太菜了。

反思反思!

简述一下建图方式:

把原图中的边看作点。

  1. S向每条边对应的的点连边,容量为边权。

  2. 每条边对应的点向这条边连接的两个点连边,容量为\(1e18\)

  3. 每个原图中的点向T连边,容量为点权。

答案即为总边权-最小割。

代码

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <cctype>
#include <algorithm>
#include <queue>
#define rin(i,a,b) for(int i=(a);i<=(b);i++)
#define rec(i,a,b) for(int i=(a);i>=(b);i--)
#define trav(i,a) for(int i=head[(a)];i;i=e[i].nxt)
using std::cin;
using std::cout;
using std::endl;
typedef long long LL;

inline int read(){
	int x=0;char ch=getchar();
	while(ch<'0'||ch>'9') ch=getchar();
	while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
	return x;
}

const int MAXN=1005;
int n,m,S,T;
int ecnt=1,head[MAXN<<1];
int a[MAXN];
int dep[MAXN<<1],cur[MAXN<<1];
LL maxflow,mincut;
std::queue<int> q;
struct Edge{
	int to,nxt;
	LL cap;
}e[MAXN<<3];

inline void add_edge(int bg,int ed,LL ca){
	ecnt++;
	e[ecnt].to=ed;
	e[ecnt].nxt=head[bg];
	e[ecnt].cap=ca;
	head[bg]=ecnt;
}

inline bool bfs(){
	memset(dep,0,sizeof dep);
	while(!q.empty()) q.pop();
	rin(i,1,T) cur[i]=head[i];
	dep[S]=1;
	q.push(S);
	while(!q.empty()){
		int x=q.front();
		q.pop();
		trav(i,x){
			int ver=e[i].to;
			if(!dep[ver]&&e[i].cap){
				dep[ver]=dep[x]+1;
				q.push(ver);
			}
		}
	}
	return dep[T]>0;
}

LL dfs(int x,LL pref){
	if(x==T||!pref) return pref;
	LL flow=0,temp;
	for(int &i=cur[x];i;i=e[i].nxt){
		int ver=e[i].to;
		if(dep[ver]!=dep[x]+1) continue;
		if(!(temp=dfs(ver,std::min(pref,e[i].cap)))) continue;
		pref-=temp;
		flow+=temp;
		e[i].cap-=temp;
		e[i^1].cap+=temp;
		if(!pref) return flow;
	}
	return flow;
}

inline void dinic(){
	while(bfs()) maxflow+=dfs(S,1e18);
}

int main(){
	n=read(),m=read();
	S=n+m+1,T=S+1;
	rin(i,1,n){
		a[i]=read();
		add_edge(m+i,T,a[i]);
		add_edge(T,m+i,0);
	}
	LL ans=0;
	rin(i,1,m){
		int u=read(),v=read();
		LL w=read();
		add_edge(S,i,w);
		add_edge(i,S,0);
		add_edge(i,m+u,1e18);
		add_edge(m+u,i,0);
		add_edge(i,m+v,1e18);
		add_edge(m+v,i,0);
		ans+=w;
	}
	dinic();
	mincut=maxflow;
	ans-=mincut;
	printf("%I64d\n",ans);
	return 0;
}

posted on 2018-11-29 15:59  ErkkiErkko  阅读(245)  评论(0编辑  收藏  举报