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


题目

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


结题思路

试题库问题很像。//听所贪心也能过
【需要注意的是:因为跟试题库问题的建图有一些区别,所以在输出的时候还要 − k -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"); 
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值