1391: [Ceoi2008]order|网络流

裸的最大权闭合图

注意要用当前弧优化

不然会T的


#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<set>
#include<map>
#include<queue>
#include<vector>
#define T 3330003
#define ll long long
using namespace std;
int sc()
{
	int i=0; char c=getchar();
	while(c>'9'||c<'0')c=getchar();
	while(c>='0'&&c<='9')i=i*10+c-'0',c=getchar();
	return i;
}
int dis[2555],q[2555],cur[2555];
int head[2555],lst[T],nxt[T],v[T];
int tot=1,n,m,S,W;
long long ans;
void insert(int x,int y,int z)
{
	lst[++tot]=y; v[tot]=z; nxt[tot]=head[x]; head[x]=tot;
	lst[++tot]=x; v[tot]=0; nxt[tot]=head[y]; head[y]=tot;
}
bool BFS()
{
	memset(dis,0,sizeof(dis)); dis[S]=1;
	int l=1,r=2;q[1]=S;
	while(l<r)
	{
		int x=q[l++];
		for(int i=head[x];i;i=nxt[i])
		    if(v[i]&&!dis[lst[i]])
		    {
		    	dis[lst[i]]=dis[x]+1;
		    	q[r++]=lst[i];
		    }
	}
	return dis[W]!=0;
}
int dfs(int x,int f)
{
	if(x==W)return f;
	int ww=0,w;
	for(int i=cur[x];i;i=nxt[i])
	    if(v[i]&&dis[lst[i]]==dis[x]+1)
	    {
	    	w=dfs(lst[i],min(f-ww,v[i]));
	    	ww+=w; v[i]-=w; v[i^1]+=w;
	    	if(v[i]>0)cur[x]=i;
	    	if(f==ww)return f;
	    }
	if(!ww)dis[x]=0;
	return ww;
}   	
int main()
{
	n=sc();m=sc();
	S=n+m+1;W=S+1;
	for(int i=1;i<=n;i++)
	{
		int x=sc(),t=sc();
		insert(S,i,x);
		for(int j=1;j<=t;j++)
		{
			int y=sc(),c=sc();
			insert(i,n+y,c);
		}
		ans+=x;
	}
	for(int i=1;i<=m;i++)
	{
		int x=sc();
		insert(n+i,W,x);
	}
	while(BFS())
	{
		for(int i=1;i<=W;i++)cur[i]=head[i];
	    ans-=dfs(S,T);
	}
	cout<<ans;
	return 0;
}


你可能感兴趣的:(网络流)