[luogu 3254] 圆桌问题 {dinic算法,网络流24题}

版权声明:请大家斧正,如喜欢的话,为拙见点一个赞吧。 https://blog.csdn.net/qq_39897867/article/details/81592823

文章目录


题目

https://www.luogu.org/problemnew/show/P3254


结题思路

试题库问题很像。//听所贪心也能过
【需要注意的是:因为跟试题库问题的建图有一些区别,所以在输出的时候还要 k -k .】


代码

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std; 
const int inf=1e6; 
struct node{
	int y,w,next; 
}a[80001];
queue<int>que; 
int k,n,m,s,t,ans,len=1,last[40001],dis[40001]; 
void add(int x,int y,int w)
{
	a[++len]={y,w,last[x]}; last[x]=len; 
	a[++len]={x,0,last[y]}; last[y]=len; 
}
bool bfs()
{
	memset(dis,0,sizeof(dis)); 
	while (!que.empty()) que.pop(); 
	dis[s]=1; que.push(s); 
	while (!que.empty()){
		int u=que.front(); que.pop(); 
		for (int i=last[u];i;i=a[i].next)
		if (a[i].w&&!dis[a[i].y]){
			dis[a[i].y]=dis[u]+1; 
			if (a[i].y==t) return 1; 
			que.push(a[i].y); 
		}
	}
	return 0; 
}
int dinic(int xq,int maxf)
{
	if (xq==t||!maxf) return maxf; 
	int ret=0,f=0; 
	for (int i=last[xq];i;i=a[i].next)
	if (a[i].w&&dis[a[i].y]==dis[xq]+1)
	{
		ret+=(f=dinic(a[i].y,min(a[i].w,maxf-ret))); 
		a[i].w-=f; a[i^1].w+=f; 
		if (maxf==ret) break; 
	}
	return ret; 
}
int main()
{
	scanf("%d%d",&k,&n); 
	int g; s=k+n+1; t=s+1; 
	for (int i=1;i<=k;i++) 	scanf("%d",&g),m+=g,add(s,i,g); 
	for (int i=1;i<=n;i++)
	{
	 	scanf("%d",&g),add(k+i,t,g); 	
		for (int j=1;j<=k;j++) add(j,k+i,1); 
	}
	while (bfs()) ans+=dinic(s,inf); 
	if (ans==m){
		printf("1\n"); 
		for (int i=1;i<=k;printf("\n"),i++)
	    {
	    	for (int j=last[i];j;j=a[j].next)
	    	if (a[j].y<=k+n&&a[j].y>k&&!a[j].w) printf("%d ",a[j].y-k); 
		}
	} else printf("0\n"); 
}

猜你喜欢

转载自blog.csdn.net/qq_39897867/article/details/81592823