【JZOJ 省選模擬】6683.我圖呢

題目

Description

在這裏插入圖片描述
Input
在這裏插入圖片描述

Output

在這裏插入圖片描述
Sample Input
5 4
100 1 2 3 4
1 2
1 3
3 4
4 5

Sample Output
3 7
01101

Data Constraint
在這裏插入圖片描述

思路

經典最小割模型
考慮先把這個圖黑白染色
然後白點連s,黑點連t
條件之間連INF的邊
把點權加上inf就可以保證選最多的點

代碼


#include<bits/stdc++.h>
#define ll long long
using namespace std;
const ll inf=4e9,INF=inf*1000,N=307;
int cnt=1,n,m,x[N],y[N],cur[N],ls[N],Ls[N],id[N],num[N],tot,b[N],bz[N],S,T,d[N];
ll w[N],ans,yjy;
struct E
{
	int to,next;
	ll f;
}e[N*N*2],E[N*N*2];
void adde(int u,int v)
{
	E[++tot].to=v; E[tot].next=Ls[u]; Ls[u]=tot;
}
void add(int u,int v,ll val)
{
	e[++cnt].to=v; e[cnt].next=ls[u]; ls[u]=cnt; e[cnt].f=val;
	e[++cnt].to=u; e[cnt].next=ls[v]; ls[v]=cnt; e[cnt].f=0;
}
void DFS(int u,int c)
{
	b[u]=c;
	if(c==0) add(S,u,w[u]),id[++id[0]]=cnt-1;else add(u,T,w[u]),id[++id[0]]=cnt-1; num[id[0]]=u;
	for(int i=Ls[u]; i; i=E[i].next)
	{
		int v=E[i].to;
		if(b[v]==-1) DFS(v,c^1);
	}
}
bool bfs()
{
	memset(d,0,sizeof(d));
	queue<int> q; q.push(S);
	d[S]=1;
	while(!q.empty())
	{
		int u=q.front(); q.pop();
		for(int i=ls[u]; i; i=e[i].next)
		{
			int v=e[i].to;
			if(d[v]==0&&e[i].f>0) d[v]=d[u]+1,q.push(v);
		}
	}
	return d[T]!=0;
}
ll dfs(int u,ll flow)
{
	if(u==T) return flow;
	ll ret=0;
	for(int i=cur[u]; i; i=e[i].next)
	{
		int v=e[i].to;
		if(d[v]==d[u]+1&&e[i].f>0)
		{
			ll aii=dfs(v,min(flow,e[i].f));
			flow-=aii;
			e[i].f-=aii;
			ret+=aii;
			e[i^1].f+=aii;
			if(!flow) break;
		}
	}
	if(!ret) d[u]=0;
	return ret;
}
void findS(int x)
{
	bz[x]=1; 
	for(int i=ls[x]; i; i=e[i].next)
		if(e[i].f>0&&!bz[e[i].to])
			findS(e[i].to);
}
void dinic()
{
	while(bfs())
	{
		for(int i=1; i<=n+2; i++) cur[i]=ls[i];
		ans-=dfs(S,INF-1);
	}
//	ll yjy=0;
//	for(int i=1; i<=id[0]; i++) if(e[id[i]].f>0) bz[num[i]]=1,yjy++;
	findS(S);
	for(int i=1; i<=n; i++) if(bz[i]^b[i]==1) yjy++;
	cout<<yjy<<' '<<ans%inf<<endl;
	for(int i=1; i<=n; i++) printf("%d",bz[i]^b[i]);
	
}
int main()
{
//	freopen("graph.in","r",stdin); freopen("graph.out","w",stdout);
	scanf("%d%d",&n,&m);
	for(int i=1; i<=n; i++) scanf("%lld",&w[i]),w[i]+=inf,ans+=w[i];
	for(int i=1; i<=m; i++) scanf("%d%d",&x[i],&y[i]),adde(x[i],y[i]),adde(y[i],x[i]);
	memset(b,-1,sizeof(b));
	S=n+1,T=n+2;
	for(int i=1; i<=n; i++) if(b[i]==-1) DFS(i,0);
	for(int i=1; i<=m; i++)
	{
		if(b[x[i]]==1) swap(x[i],y[i]);
		add(x[i],y[i],INF);
	}
	dinic();
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章