其他分享
首页 > 其他分享> > CF36E Two Paths

CF36E Two Paths

作者:互联网

XXXV.CF36E Two Paths

为什么这题会被归到数据结构博客里呢?因为我的代码使用了大剂量的 STL

我吹爆 list 有没有!再也不手写链表了(并不),但是在欧拉路问题上真的贼好用!

首先,覆盖所有边恰一次,妥妥的欧拉路模型。

然后就先考虑如何判无解了。怎样无解呢?

  1. 有少于 \(2\) 条边。(如果不是样例给了,大概很难注意到……)

  2. 有超过 \(2\) 个连通块。

  3. 仅有一个连通块,且连通块中奇点数大于 \(4\)。

  4. 有两个连通块,且其中某一个块中奇点数大于 \(2\)。

那么,是否所有条件都满足,就一定有解呢?

是的。

假如从欧拉路的方向考虑,就会非常麻烦,因为你找出的欧拉路删去后可能使得这张图分成许多不连通的图。

因此,这里有一个很好的思路:在两个奇点间连边,这样就会转换为欧拉回路,然后在欧拉回路上断去新加的边就行了。

具体而言,对于两个连通块的情形,显然上述结论正确,因为每个连通块都必然符合条件。

然后,对于仅有一个连通块的情形,其中可能有 \(0\) 个,\(2\) 个或是 \(4\) 个奇点。

\(0\) 个奇点就搜出回路然后随便砍两刀断环成链即可。

\(2\) 个奇点就在额外连的那条边处砍一刀,然后再随便砍一刀就行。

\(4\) 个奇点这两刀必须砍在额外的两条边的位置。这形成的两条链必然非空,因为这两条新边必然无公共端点,即其在欧拉环上必然不相邻。

时间复杂度 \(O(m)\)。

致死量 STL 的代码:

#include<bits/stdc++.h>
using namespace std;
int m,n,X[10010],Y[10010],dsu[20010],lim,id[20010];
bool deg[20010],used[10010];
vector<int>v,u[20010],w[20010];
int find(int x){return dsu[x]==x?x:dsu[x]=find(dsu[x]);}
void merge(int x,int y){
	x=find(x),y=find(y);
	if(x==y)return;
	dsu[y]=x;
}
#define lst list<int>::iterator
list<int>ls;
void dfs(lst pos,int x){
	while(true){
		while(!w[x].empty()&&used[w[x].back()])w[x].pop_back();
		if(w[x].empty())return;
		int i=w[x].back(),y=X[i]^Y[i]^x;w[x].pop_back(),used[i]=true;
		dfs(ls.insert(pos,i),y);
	}
}
vector<int>s[3];
int main(){
	freopen("input.txt","r",stdin);
	freopen("output.txt","w",stdout);
	scanf("%d",&m);
	for(int i=1;i<=m;i++)scanf("%d%d",&X[i],&Y[i]),v.push_back(X[i]),v.push_back(Y[i]);
	if(m==1){puts("-1");return 0;}
	sort(v.begin(),v.end()),v.resize(n=unique(v.begin(),v.end())-v.begin());
	for(int i=1;i<=n;i++)dsu[i]=i;
	for(int i=1;i<=m;i++)merge(X[i]=lower_bound(v.begin(),v.end(),X[i])-v.begin()+1,Y[i]=lower_bound(v.begin(),v.end(),Y[i])-v.begin()+1),deg[X[i]]^=1,deg[Y[i]]^=1;
//	for(int i=1;i<=m;i++)printf("%d %d\n",X[i],Y[i]);
//	for(int i=1;i<=n;i++)printf("(%d,%d)",find(i),deg[i]);puts("");
	for(int i=1;i<=n;i++)if(dsu[i]==i)id[i]=++lim;
	for(int i=1;i<=n;i++)u[id[find(i)]].push_back(i);
	if(lim>=3){puts("-1");return 0;}
	for(int i=1;i<=m;i++)w[X[i]].push_back(i),w[Y[i]].push_back(i);
	if(lim==1){
		vector<int>sp;
		for(auto i:u[1])if(deg[i])sp.push_back(i);
		if(sp.size()>4){puts("-1");return 0;}
		for(int i=0;i<sp.size();i+=2){
			int eid=m+i/2+1;
			X[eid]=sp[i],Y[eid]=sp[i+1],w[sp[i]].push_back(eid),w[sp[i+1]].push_back(eid);
		}
		dfs(ls.begin(),u[1].back());
//		printf("%d\n",sp.size());
		if(sp.empty()){
			s[1].push_back(ls.front()),ls.pop_front();
			for(auto i:ls)s[2].push_back(i);
		}
		if(sp.size()==2){
			while(ls.front()<=m)ls.push_back(ls.front()),ls.pop_front();
			ls.pop_front();
			s[1].push_back(ls.front()),ls.pop_front();
			while(!ls.empty())s[2].push_back(ls.front()),ls.pop_front();
		}
		if(sp.size()==4){
			while(ls.front()<=m)ls.push_back(ls.front()),ls.pop_front();
			ls.pop_front();
			while(ls.front()<=m)s[1].push_back(ls.front()),ls.pop_front();
			ls.pop_front();
			while(!ls.empty())s[2].push_back(ls.front()),ls.pop_front();
		}
	}
	if(lim==2){
		for(int i=1;i<=2;i++){
			ls.clear();
			vector<int>sp;
			for(auto j:u[i])if(deg[j])sp.push_back(j);
			if(sp.size()>2){puts("-1");return 0;}
			if(!sp.empty())X[m+1]=sp[0],Y[m+1]=sp[1],w[sp[0]].push_back(m+1),w[sp[1]].push_back(m+1),used[m+1]=false;
			dfs(ls.begin(),u[i].back());
			if(!sp.empty()){while(ls.front()<=m)ls.push_back(ls.front()),ls.pop_front();ls.pop_front();}
			while(!ls.empty())s[i].push_back(ls.front()),ls.pop_front();
		}
	}
	for(int i=1;i<=2;i++){
		printf("%d\n",s[i].size());
		for(auto j:s[i])printf("%d ",j);puts("");
	}
	return 0;
}

标签:Paths,连通,CF36E,int,sp,Two,奇点,back,return
来源: https://www.cnblogs.com/Troverld/p/14612734.html