P9705 「TFOI R1」Unknown Graph 题解

题目传送锚点

在博客园食用更佳

这道题的正解是网络流。但是这个正解实在是不太好想,因为题意是让你构造一个满足输入要求的图,并没有出现一星半点儿能让人联想到网络流的线索。

那么这道题怎么建图呢?

首先,当我们看见每个点都有两个描述——入度和出度。既然如此麻烦,何不拆点建图?嗯,有道理。步骤如下:

  1. 将入度点 xi 连向超级汇点,长度为这个点的入度数(即 ai);
  2. 将出度点 yi 连向超级源点,长度为这个点的出度数(即 bi);
  3. 将入度点连向所有出度点。注意不能自环,不能忽略特殊限制。

然后就建完图了。

在此基础上跑一遍网络流即可。为什么呢?因为你在跑网络流的时候,如果选择了 xiyi 这条边,就说明建图的时候要选择这条边。那么输出时只要发现满了的这种边,就输出它。

今天破例贴个代码吧。用的某 Dinic,并没有加当前弧优化。

#include<bits/stdc++.h>
#define int long long
using namespace std;

int n,m,s,t,x,y,z,ans,cnt=1,dist[5000000],head[5000000],xz[1001][1001];

struct node
{
	int start;
	int to;
	int v;
	int next;
}a[5000000];

void add(int x,int y,int z)
{
	a[++cnt].start=x;
	a[cnt].to=y;
	a[cnt].v=z;
	a[cnt].next=head[x];
	head[x]=cnt;
	a[++cnt].start=y;
	a[cnt].to=x;
	a[cnt].v=0;
	a[cnt].next=head[y];
	head[y]=cnt;
}

int bfs()										
{
	for(int i=s;i<=t;++i) dist[i]=0x7fffffff;
	queue<int>q;								
	q.push(s);								
	dist[s]=0;								
	while(!q.empty())				
	{	
		int x=q.front();		
		q.pop();					
		for(int i=head[x];i;i=a[i].next)		
		{
			int y=a[i].to;					
			if(a[i].v>0&&dist[y]==0x7fffffff)	
			{
				q.push(y);					
				dist[y]=dist[x]+1;				
				if(y==t) return 1;				
			}
		}
	}
	return 0;
}

int dfs(int x,int sum)
{
	if(x==t) return sum;						
	int k,res=0;								
	for(int i=head[x];i&&sum;i=a[i].next)		
	{			
		int y=a[i].to;							
		if(a[i].v>0&&dist[y]==dist[x]+1)		
		{
			k=dfs(y,min(sum,a[i].v)); 
			if(k==0) dist[y]=0x7fffffff;
			a[i].v-=k;
			a[i^1].v+=k;
			res+=k;
			sum-=k;
		}
	}
	return res;
}

signed main()
{
	ios::sync_with_stdio(false);
	cin.tie(); 
	cin>>n;
	s=0;
	t=2*n+1;
	for(int i=1;i<=n;++i)
	{
		cin>>x;
		add(i+n,t,x);
	}
	for(int i=1;i<=n;++i)
	{
		cin>>x;
		add(s,i,x);
	}
	cin>>m;
	for(int i=1;i<=m;++i)
	{
		cin>>x>>y;
		xz[x][y]=1;
	}
	for(int i=1;i<=n;++i) for(int j=1;j<=n;++j) if(i!=j&&!xz[i][j]) add(i,j+n,1);
	while(bfs())
	{
		ans+=dfs(s,0x7fffffff);
	}
	cout<<ans<<endl;
	for(int i=4*n-1;i<=cnt;++i)
	{
		if(a[i].start==s||a[i].to==t||i%2==1) continue;
		if(a[i].v==0) cout<<a[i].start<<" "<<a[i].to-n<<"\n";
	}
	return 0;
}
posted @   cath20  阅读(3)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示