zoukankan      html  css  js  c++  java
  • 【训练题】无序字母对 P1675

    Description

    给定n个各不相同的无序字母对(区分大小写,无序即字母对中的两个字母可以位置颠倒)。请构造一个有n+1个字母的字符串使得每个字母对都在这个字符串中出现。


    Input

    第一行输入一个正整数n.以下n行每行两个字母,表示这两个字母需要相邻。


    Output

    输出满足要求的字符串。如果没有满足要求的字符串,请输出“No Solution”。如果有多种方案,请输出前面的字母的ASCII编码尽可能小的(字典序最小)的方案。


    Hint

    不同的无序字母对个数有限,n的规模可以通过计算得到


    Solution

    这道题需要计算一条欧拉路径,无序所以是无向图,由于数据规模较大用邻接矩阵来存会爆RE所以这个无向图只能用用vector来存,存的是char字符和每条边的id。字典序需要最小所以输入所有路径后需要将g从小到大进行排序。然后vector一个ep序列记录欧拉路径树的后序遍历结果,这里有一个需要注意的地方详见注意事项。


    判断无解就需要记录每个结点的度,如果不等于0和2(即不是欧拉回路或者欧拉路),那么就直接输出无解后retrun 0。如果满足条件,因为字典序要最小所以要找到第一个最小的奇点,并且将start更新成它。如果没有奇点那么在init中已经将start更新成字典序最小的结点作为路径的开端了。然后就是欧拉路径dfs。


    注意事项:

    1.因为vector是从0位置开始输入并且size()返回的是+1的大小所以循环的时候从0开始且结束循环不用取等。
    2.输入的时候不要用getchar()因为getchar会把回车输进去所以用一个str数组存字符串然后使起点和终点等于str[0]和str[1]。
    3.存的是无向图所以一条边id要一样。
    4.排序的时候循环是从字符'A'到'z',不是从1到n。
    5.输出的时候将后序遍历结果倒着输出,同样需要注意size()不取等,结束在0位置。

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    #define maxn 100005
    using namespace std;
    struct edge{
    	char v;
    	int id;
    };
    char x,y,start;
    int n,cnt;
    char str[5];
    int num[maxn];
    bool vis[maxn];
    vector<edge>g[maxn];
    vector<char>ep;
    bool cmp(edge x,edge y){
    	return x.v<y.v;
    }
    void init(){
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++){
    		scanf("%s",str);
    		x=str[0];
    		y=str[1];
    		if(i==1)start=x;
    		if(start>x)start=x;
    		if(start>y)start=y;
    		g[x].push_back((edge){y,i});
    		g[y].push_back((edge){x,i});
    		num[x]++;
    		num[y]++;
    	}
    	for(int i='A';i<='z';i++)
    	sort(g[i].begin(),g[i].end(),cmp);
    }
    void find_circle(char x){
    	for(int k=0;k<g[x].size();k++){
    		char j=g[x][k].v;
    		int id=g[x][k].id;
    		if(vis[id])continue;
    		else vis[id]=true;
    		find_circle(j);
    	}
    	ep.push_back(x);
    }
    int main(){
    	init();
    	for(char i='A';i<='z';i++){
    		if(num[i]%2==1){
    			cnt++;
    		}
    	}
    	if(cnt!=0&&cnt!=2){
    		printf("No Solution
    ");
    		return 0;
    	}
    	if(cnt==2){
    		for(int i='A';i<='z';i++){
    			if(num[i]&1){
    				start=i;
    				break;
    			}
    		}
    	}
    	find_circle(start);
    	for(int p=ep.size()-1;p>=0;p--){
    		printf("%c",ep[p]);
    	}
    	putchar('
    ');
    	return 0;
    }
    
  • 相关阅读:
    IE9以下程序开发不兼容项目罗列
    Flutter编程:Flutter命令行的学习
    Git merge 和 rebase 进一步比较
    Git merge rebase cherry-pick 以及 游离commit 的测试
    C++指针传递和引用传递的区别 (转载整理)
    git 填坑之 git 暂存区忽略文件
    小众软件:Windows 下优化软件推荐—— Dism++ | 强迫症晚期患者福音
    pip 安装库的时候使用豆瓣镜像 提升效率
    gitignore 忽略某文件夹下 非某后缀名的文件
    小众软件:画简洁风格的原型图
  • 原文地址:https://www.cnblogs.com/virtual-north-Illya/p/10044986.html
Copyright © 2011-2022 走看看