【bzoj 1934】[Shoi2007]Vote 善意的投票 最小割

额,我的是有多久没写网络流了 。。。。手生了

以前对于最小割的理解局限于最大流的演变上,我觉得这道题是一个很好的例子。我们将同意的和s连边,边权为一,将不同意的和t连边边权为1,朋友之间连边,边权还是一,这样一来,点与点之间就建立了联系,比如现在我要让一个原本统一的人不同意,在我们建立的图上面就相当于划掉他和他原来的点之间的连线,而割掉这一条边以后对于答案的贡献就是1,或者说让一个朋友和另外一个朋友产生矛盾,也只需要划去两个朋友之间的连线,同样的,当我们找到一条最小割以后将图 分成了s和t集合而这两个集合之间一定不会有任意两个人之间产生矛盾。因此,问题转变成了最小割问题

本人觉得因该是对于最小割更为本质的应用吧

#include
#include
#include
#define maxn 310
using namespace std;
int n,s,t,head[maxn],tot,m,d[maxn],last[maxn],vd[maxn];
struct edge{
	int v,w,next;
}e[maxn*maxn*2];
void adde(int a,int b,int c){e[tot].v=b,e[tot].w=c,e[tot].next=head[a];head[a]=tot++;}

int dfs(int u,int flow){
	if(u==t)return flow;
	int res=0,temp=0;
	for(int i=last[u];i!=-1;i=e[i].next )if(d[u]==d[e[i].v]+1&&e[i].w>0){
		last[u]=i;
		temp=dfs(e[i].v,min(e[i].w,flow-res));//我擦 一开始写成了flow-e[i].w找了好久 
		res+=temp,e[i].w-=temp,e[i^1].w+=temp;
		if(res==flow)return res;
	}
	if(d[s]>=t)return res;
	vd[d[u]]--;if(vd[d[u]]==0)d[s]=t;
	d[u]++;vd[d[u]]++;
	last[u]=head[u];
	return res;
}

void sap(){
	int ans=0;
	for(int i=0;i<=t;i++)last[i]=head[i];
	while(d[s]


你可能感兴趣的:(ac之路,bzoj,网络流)