zoukankan      html  css  js  c++  java
  • 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;
    }
    

  • 相关阅读:
    group_concat函数与find_in_set()函数相结合
    PHP获取指定时间的上个月
    CI框架 数据库批量插入 insert_batch()
    PHP可变长函数方法介绍
    js闭包理解
    Android百度地图开发(一)之初体验
    Activity的四种启动模式和onNewIntent()
    再探Java基础——throw与throws
    Failed to load JavaHL Library解决方法
    Eclipse中添加Android系统jar包
  • 原文地址:https://www.cnblogs.com/Troverld/p/14612734.html
Copyright © 2011-2022 走看看