zoukankan      html  css  js  c++  java
  • P1341 无序字母对

    按照题意建图,然后要求欧拉路径,对一个欧拉路径的判定
    欧拉回路属于欧拉路径,而欧拉路径要求远比欧拉回路要求低。

    无向图 当且仅当图中有两点度数为奇数,这两点为起点和终点,其他点度数皆为偶数且联通。
    有向图 当且仅当其中一个顶点的入度少于出度1(起点),而另一点出度少于入度1(终点),其余节点出度=入度。图联通时。

    至于为什么要倒着存,可以这样解释
    input:
    5
    xx
    xa
    aa
    ab
    bx
    output 50pts:
    aabxax
    output 100pts:
    aabxxa

    可以发现,50pts代码会贪心地挑较小结点访问,当访问到倒数第三个字母x时,会毫不犹豫地前往a,而不管这样做是否能遍历完,因此走到a无路可走了,又回到x遍历另外一个x,从而得到一个错误的答案
    而100pts代码的好处在于,它是在遍历结束后将该结点逆序存入答案中,这就保证了无路可走的节点a一定是该序列的结尾(因为如果该结点还能继续访问,它就一定在那些能继续访问的点的前面),然后回到倒数第三个字母x寻找下一个x访问。此处不用担心x是否也是一个结尾(那样就无解了),因为通过递归前的判断,这张图中一定存在欧拉路,也就是只有一个终点

    const int N=10007;
    int m;
    std::string s;
    int g[N][N];
    int ot[N];
    char a[N];
    int ans;
    inline void print(){
    	drp(i,ans,1){
    		cout<<a[i];
    	}
    	cout<<'\n';
    }
    
    inline void dfs(int x){
    	rep(j,1,150){
    		if(g[x][j]){
    			--g[x][j];
    			--g[j][x];
    			dfs(j);
    		}
    	}
    	a[++ans]=x;
    }
    int main(){
    	std::ios::sync_with_stdio(false);
    	cin>>m;
    	rep(i,1,m){
    		cin>>s;
    		++g[s[0]][s[1]];
    		++g[s[1]][s[0]];
    		++ot[s[0]];
    		++ot[s[1]];
    	}
    	int cnt(0),a(0);
    	rep(i,1,150){
    		if(ot[i]&1){
    			++cnt;
    			if(!a) a=i;
    		}
    	}
    	if(!a) {
    		rep(i,1,150){
    			if(ot[i]) {
    				a=i;
    				break;
    			}
    		}
    	}
    	
    	if(cnt&&cnt!=2){
    		puts("No Solution");
    		return 0;
    	}
    	dfs(a);
    	if(ans!=m+1){
    		puts("No Solution");
    		return 0;
    	}
    	print();
    	return 0;
    }
    

    本文来自博客园,作者:{2519},转载请注明原文链接:https://www.cnblogs.com/QQ2519/p/15573657.html

  • 相关阅读:
    C++11 override和final
    C++11 类型推导auto
    C++11 强枚举类型
    C++11 explicit的使用
    《数据结构与算法之美》——冒泡排序、插入排序、选择排序
    《数据结构与算法之美》- 栈
    Spring Boot系列——AOP配自定义注解的最佳实践
    Spring Boot系列——死信队列
    Spring Boot系列——7步集成RabbitMQ
    让我头疼一下午的Excel合并单元格
  • 原文地址:https://www.cnblogs.com/QQ2519/p/15573657.html
Copyright © 2011-2022 走看看