bzoj1934 [Shoi2007] Vote goodwill vote minimum cut

It is easy to think of contracting dp at first, but since a set cannot be represented by state, it cannot be dp

Then you can think of the minimum cut, which is to complete the distribution through the cut edge and the cost;

It is better to do it. The default selection of 0 is to connect the edge to 0, and the default selection of 1 is to connect the edge to 1. Friends are connected to each other. If there is no traffic in the same set, the cost will be incurred in different sets. 1 flow

code:

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
#define N 900005
#define inf 1000000009
queue<int>q;
int tot=-1,hou[N],xia[N],zhong[N],yuan[N],v[N],d[N],s,t,n,m,x,y,i;
void jian(int a,int b,int c)
{
	++tot;hou[tot]=yuan[a],zhong[tot]=b,yuan[a]=tot,v[tot]=c;
}
void jia(int a,int b,int c)
{
	jian(a,b,c);
	jian(b,a,0);	
}
bool bfs()
{
	int i,j;
	for(i=1;i<=t;i++)
	{
		xia[i]=yuan[i];d[i]=inf;				
	}
	d[s]=0;
	q.push(s);
	while(!q.empty())
	{
		int st=q.front();
		q.pop();
		for(i=xia[st];i!=-1;i=hou[i])
		{ if(v[i]==0)continue;
			int nd=zhong[i];
		  if(d[nd]==inf)d[nd]=d[st]+1,q.push(nd);			
		}	
	}	
	return d[t]!=inf;
}
int dfs(int o,int limit)
{
	if(o==t||limit==0)return limit;
	int i,f,flow=0;
	for( i=xia[o];i!=-1;i=hou[i])
	{
		xia[o]=i;
		int nd=zhong[i];
		if(d[nd]==d[o]+1&&(f=dfs(nd,min(limit,v[i]))))
		{
			flow+=f;
			limit-=f;
			v[i]-=f;
			v[i^1]+=f;
			if(limit==0)break;		
		}
	}
	return flow;
}
int dinic()
{
int ans=0;
while(bfs())
{
ans+=dfs(s,inf);	
}	return ans;
}
int main()
{
	memset(yuan,-1,sizeof(yuan));
	scanf("%d%d",&n,&m);
	s=n+1;t=n+2;
	for(i=1;i<=n;i++)
	{
		scanf("%d",&x);
		if(x==1)jia(i,t,1);
		else jia(s,i,1);
	}
	for(i=1;i<=m;i++)
scanf("%d%d",&x,&y),jia(x,y,1),jia(y,x,1);
	printf("%d",dinic());
}


Guess you like

Origin blog.csdn.net/haobang866/article/details/79238684