Icy Itinerary(一道有意思的增量构造题)

原题链接:Icy Itinerary - Problem - QOJ.ac

题意

给定一个图,有n个点,m条边,要求构造一个以1开头点的排列,使得该排列中只存在一个点ai满足:ai与ai-1和ai+1的其中一点有连边,且与另外一点无连边。

数据规模:n,m≤3e5

题目理解

将原题意翻译一下,就是说要求我们将原图划分为两个互补的集合,使得其中一个集合中存在一条哈密顿路,另一个集合的补图中存在一条哈密顿路。

证明:假设ai-1与ai之间有连边,ai+1与ai之间没有连边,则易推出ai-1与ai-2,ai-2与ai-3…之间一定有连边,而ai+1与ai+2,ai+2与ai+3…之间无连边,则a1…i这个集合中相邻两点有连边,ai+1…n这个集合中相邻两点无连边。即可知题意实际为将原图划分为两个互补的集合,使得其中一个集合中存在一条哈密顿路,另一个集合的补图中存在一条哈密顿路。

对于这个构造,我们可以这样考虑:假设我们已知s1为原图中存在哈密顿路的集合,t1为该哈密顿路的终点,s2为补图中存在哈密顿路的集合,t2为该补图中哈密顿路的终点,ai为我们当前考虑加入的点。

 此时有三种情况:

1.ai与t1之间有连边,则可以将ai加入s1,并将ai作为新的t1;

2.ai与t2之间无连边,则可以将ai加入s2,并将ai作为新的t2;

3.ai与t1之间无连边,且ai与t2之间有连边,此时又有两种情况:

若t1与t2之间有连边,不难发现t1-t2-ai为一条哈密顿路,则我们可以将t2从s2中取出,并加入s1,然后再将ai加入s1;

 若t1与t2之间无连边,不难发现t2-t1-ai为补图中的一条哈密顿路,则我们可以将t1从s1中取出,并加入s2,然后再将ai加入s2。

细节思考

1.当s1和s2中有一个空集时,我们应当优先考虑将新的节点放入空集,避免将虚假节点放入集合;

2.由于题目要求构造以1开头的排列,所以我们可以考虑倒序加入节点,并记录1节点所在集合,再倒序输出,保证1节点一定在开头。

代码实现

#include<bits/stdc++.h>
using namespace std;
int const N=1e6+10;
map<int,int>G[N];
int pa1[N],pa2[N],n,m,cnt1,cnt2;
int main(){
	cin>>n>>m;
	if(m==0){
		for(int i=1;i<=n;i++)cout<<i<<" ";
		return 0;
	}
	for(int i=1;i<=n;i++)G[0][i]=G[i][0]=1;
	for(int i=1;i<=m;i++){
		int x,y;
		cin>>x>>y;
		G[x][y]=1;
		G[y][x]=1;
	}
	for(int i=n;i>=1;i--){
		if(G[i][pa1[cnt1]])pa1[++cnt1]=i;
		else{
			if(!G[i][pa2[cnt2]])pa2[++cnt2]=i;
			else{
				if(G[pa1[cnt1]][pa2[cnt2]]){
					if(cnt2){
						pa1[++cnt1]=pa2[cnt2];
						pa1[++cnt1]=i;
						cnt2--;
					}
					else{
						pa2[++cnt2]=i;
					}
				}
				else{
					pa2[++cnt2]=pa1[cnt1];
					pa2[++cnt2]=i;
					cnt1--;
				}
			}
		}
	}
	if(pa1[cnt1]==1){
		for(int i=cnt1;i>=1;i--)cout<<pa1[i]<<" ";
		for(int i=cnt2;i>=1;i--)cout<<pa2[i]<<" ";
	}
	else{
		for(int i=cnt2;i>=1;i--)cout<<pa2[i]<<" ";
		for(int i=cnt1;i>=1;i--)cout<<pa1[i]<<" ";
	}
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值