萌新求教
查看原帖
萌新求教
193158
michael_song楼主2021/8/13 21:56
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
const int N=105,M=250005,inf=0x3f3f3f3f,s=10001,t=10002;
int cnt=1,head[N*N],flowa[N*N],dis[N*N],l[N],c[N],pre[2*N*N];
int idl[N][N],lst[N*N],tot,result,maxflow,total,m,n,k;
bool mapl[N][N],vis[N*N];
inline int read()
{
	int w=1,f=0;
	char c=getchar();
	while(c<'0'||c>'9')
	{
		if(c=='-')
			w=-1;
		c=getchar();
	}
	while(c>='0'&&c<='9')
	{
		f=f*10+c-'0';
		c=getchar();
	}
	return w*f;
}
inline int minn(int a,int b)
{
	if(a<b)
		return a;
	else
		return b;
}
struct edge
{
	int next,u,v,w,c;
}e[M<<1];
void addedge(int u,int v,int w,int c)
{
	e[++cnt].next=head[u];
	head[u]=cnt;
	e[cnt].u=u;
	e[cnt].v=v;
	e[cnt].w=w;
	e[cnt].c=c;
}
bool SPFA()
{
	memset(dis,inf,sizeof(dis));
	memset(vis,false,sizeof(vis));
	memset(flowa,inf,sizeof(flowa)); 
	queue<int> Q;
	Q.push(s);
	dis[s]=0;
	vis[s]=true;
	pre[t]=-1;
	while(!Q.empty())
	{
		int u=Q.front();
		for(int i=head[u];i;i=e[i].next)
		{
			int v=e[i].v;
			if(e[i].w&&dis[v]>dis[u]+e[i].c)
			{
				dis[v]=dis[u]+e[i].c;
				lst[v]=i;
				pre[v]=u;
				flowa[v]=minn(flowa[u],e[i].w);
				if(!vis[v])
				{
					vis[v]=true;
					Q.push(v);
				}
			}
		}
		vis[u]=false;
		Q.pop();
	}
	return pre[t]!=-1;
}
void Dinic()
{
	while(SPFA())
	{
		int u=t;
		maxflow+=flowa[t];
		result+=flowa[t]*dis[t];
		while(u!=s)
		{
			e[lst[u]].w-=flowa[t];
			e[lst[u]^1].w+=flowa[t];
			u=pre[u];
		}
	}
}
int main()
{
	int x,y;
	n=read();m=read();k=read();
	for(int i=1;i<=n;i++)
	{
		l[i]=read();
		total+=l[i];	
	}
	for(int i=1;i<=m;i++)
	{
		c[i]=read();	
		total+=c[i];
	}
	for(int i=1;i<=k;i++)
	{
		x=read();y=read();
		mapl[x][y]=true;
	}
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
			idl[i][j]=++tot;
	for(int i=1;i<=n;i++)
		if(l[i]>0) 
		{
			addedge(idl[i][m],t,l[i],0);
			addedge(t,idl[i][m],0,0);
		}
	for(int i=1;i<=m;i++)
		if(c[i]>0)
		{
			addedge(idl[n][i],t,c[i],0);
			addedge(t,idl[n][i],0,0);
		}

	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
		{
			if(!mapl[i][j])
			{
				addedge(s,idl[i][j],2,1);
				addedge(idl[i][j],s,0,-1);
				if(j!=m)
				{
					addedge(idl[i][j],idl[i][m],1,0);
					addedge(idl[i][m],idl[i][j],0,0);
				}
				if(i!=n)
				{
					addedge(idl[i][j],idl[n][j],1,0);
					addedge(idl[n][j],idl[i][j],0,0);	
				}
			}
		}
	Dinic();
/*
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=m;j++)
		{
			printf("*%d ",idl[i][j]);
		}
		printf("\n");
	}
*/
	for(int i=head[s];i;i=e[i].next)
	{
		printf("*%d %d\n",e[i].v,e[i].w);
		if(e[i].w==0)
			result--;	
	}
	if(maxflow<total)
		printf("JIONG!");
	else
		printf("%d",result);
	return 0;
}

思路是对于每个没有障碍的点,由超级源点向他连流量为2,费用为1的边,对于每一个在行/列末尾的点,向超级汇点连一条容量为该行要求容量的边,最后把流量为2的点减去一次贡献

这破烂玩意已经调了n久了,求助\fad

我菜死了

2021/8/13 21:56
加载中...