poj2337欧拉回路

对字符串从小到大排序,邻接表正向插入。

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <stack>
#include <queue>
#include <vector>
#include <map>
#include <string>
#include <iostream>
using namespace std;
const int maxn=2222;

int cmp(const string &a,const string &b)
{
    return a<b;
}

struct Node
{
    int to;int val;int vis;
};
string str[maxn];
vector<Node> head[maxn];
int vis[maxn];
int father[100];
void add(int from,int to,int val,int vis )
{
    Node k; k.to=to; k.val=val;k.vis=vis;
    head[from].push_back(k);
}

int getfather(int x)
{
    if(x!=father[x]) father[x]=getfather(father[x]);
    return father[x];
}

void link(int a,int b)
{
    int fa=getfather(a);int fb=getfather(b);
    father[fa]=fb;
}
stack<string >  q;
void dfs(int x)
{
    int len=head[x].size();
        for(int i=0;i<len;i++){
        if(!head[x][i].vis){
            //cout<<x<<" "<<head[x][i].to<<endl;
            head[x][i].vis=1;
            dfs(head[x][i].to);
            q.push(str[head[x][i].val]);
        }
    }
}
void output()
{
    string a= q.top(); q.pop();
    cout<<a;
    while(!q.empty()){
        cout<<"."<<q.top();
        q.pop();
    }
}
int in[100];
int out[100];
int main()
{
    int Icase;
    cin>>Icase;
    int n;
    while(Icase--){
        memset(vis,0,sizeof(vis));
        for(int i=0;i<26;i++)
            father[i]=i;
        memset(in,0,sizeof(in));
        memset(out,0,sizeof(out));
        for(int i=0;i<=maxn;i++)
            head[i].clear();
        cin>>n;
        for(int i=0;i<n;i++)
            cin>>str[i];
        sort(str,str+n,cmp);
        for(int i=0;i<n;i++){
            int a=str[i][0]-‘a‘; int len=str[i].size();int b=str[i][len-1]-‘a‘;
            add(a,b,i,0); vis[a]=1;vis[b]=1; in[b]++;out[a]++; link(a,b);
        }
        int ans=0;
        for(int i=0;i<26;i++)
            if(vis[i]) if(i==father[i]) ans++;
        int flag=0;int in1=0;int out1=0;int sign;int sign1;
        for(int i=0;i<26;i++)
        if(vis[i]) {
            sign1=i;break;
        }
        for(int i=0;i<26;i++)
        if(vis[i]){
            if(in[i]==out[i]) continue;
            if(in[i]-out[i]==1){
                in1++;
            }
            if(out[i]-in[i]==1){
                out1++; sign=i;
            }
            if(out[i]-in[i]>1||out[i]-in[i]>1){
                flag=1;break;
            }
        }
        //cout<<sign<<endl;system("pause");
        if(!flag) if(in1>1||out1>1) flag=1;
        if(ans!=1||flag) cout<<"***"<<endl;
        else{
            if(in1!=0) dfs(sign);
            else dfs(sign1);
            output();
            cout<<endl;
        }
    }
    return 0;
}

poj2337欧拉回路

时间: 2024-10-11 11:50:12

poj2337欧拉回路的相关文章

[poj2337]求字典序最小欧拉回路

注意:找出一条欧拉回路,与判定这个图能不能一笔联通...是不同的概念 c++奇怪的编译规则...生不如死啊... string怎么用啊...cincout来救? 可以直接.length()我也是长见识了... CE怎么办啊...g++来救? #include<cstdio> #include<iostream> #include<cstring> #include<cmath> #include<algorithm> #define N 2020

poj2337 欧拉路径

poj2337 这道题昨天晚上开始做,今天才A.但是问题想透了, 发现其实没那么难 题目大意: 给你一些单词,如果一个单词的末尾字符与另一个单词首字符相同,则两个的单词可以连接.问是否可以把所有单词连接起来,并且每个单词只能用一次. 分析: 可以把每个单词看成是一条边,单词的首尾字符看做是两个相连的点.我们可以把它看成有向图的欧拉路径问题(欧拉路径,欧拉回路不太明白的自己百度吧). 一个有向图含有欧拉通路,首先图是连通的,并且当且仅当该图所有顶点的入度 =出度, 或者起始顶点入度 = 出度 -

poj 2337 欧拉回路按照最小字典序输出+注意为了按最小字典序怎么处理邻接表

http://poj.org/problem?id=2337 WA了好久,昨晚1点多睡不着写的,狂WA,当时是因为用邻接矩阵存储,比如aba,aa只能存下一个,这个之前还没遇到过,今天才注意到--邻接矩阵无法存储平行边, 关于欧拉回路判断看我另几篇日志或者看我的欧拉总结 再贴个输出欧拉回路的模板 其中,参数u是起点,注意如果是输出欧拉路径的话,u必须是出度比入度大一的那个点,如果输出欧拉回路,随便按要求找个就行 void euler(int u) { for(int i=head[u];i!=-

欧拉路,欧拉回路小结(转)

欧拉路,欧拉回路小结 把欧拉路和欧拉回路做一个小总结,包含了一些题目,以后遇到新的我还会陆续加上. 定义: 给定无孤立结点图G,若存在一条路,经过G中每条边有且仅有一次,称这条路为欧拉路,如果存在 一条回路经过G每条边有且仅有一次,称这条回路为欧拉回路.具有欧拉回路的图成为欧拉图. 关于欧拉路和欧拉回路定义及存在证明请看这里. 这里给出欧拉路和欧拉回路存在条件的结论: 存在欧拉路的条件: 无向图:  图连通,所有点都是偶数度,或者只有两个点是奇数度.当所有点是偶数度时欧拉路起点可以是任意 点:当

POJ2337 Catenyms 欧拉路径的输出

题目链接: poj2337 题意: 给出一些字符串,问能否将这些字符串  按照 词语接龙,首尾相接  的规则 使得每个字符串出现一次 如果可以 按字典序输出这个字符串序列 解题思路: 1.将每个字符串的首尾单词理解为图中的点,将字符串理解为边构图 2根据入度出度判断是否能构成欧拉路径 3并查集判断连通性 4将所有字符串按字典序排序可以使用sort排序 5欧拉路径的输出    用到fluery算法的思想: 设G 为一无向欧拉图,求G 中一条欧拉回路的算法为: 1) 任取G 中一顶点v0,令P0 =

混合图的欧拉回路判定

对于有向图和无向图的欧拉回路判定,很容易做到.那对于混合图呢?? 混合图就是图中既存在无向边又存在有向边的图. 至于解法: 转载自这里 把该图的无向边随便定向,计算每个点的入度和出度.如果有某个点出入度之差为奇数,那么肯定不存在欧拉回路.因为欧拉回路要求每点入度 = 出度,也就是总度数为偶数,存在奇数度点必不能有欧拉回路. 好了,现在每个点入度和出度之差均为偶数.那么将这个偶数除以2,得x.也就是说,对于每一个点,只要将x条边改变方向(入>出就是变入,出>入就是变出),就能保证出 = 入.如果

hdu1116 欧拉回路

1 //Accepted 248 KB 125 ms 2 //欧拉回路 3 //以26个字母为定点,一个单词为从首字母到末尾字母的一条边 4 //下面就是有向图判断欧拉回路 5 //连通+节点入度和==出度和 或者 存在一对节点一个入度比出度大1,一个小1 6 #include <cstdio> 7 #include <cstring> 8 #include <iostream> 9 #include <queue> 10 using namespace s

POJ 1041 John&#39;s trip 无向图的【欧拉回路】路径输出

欧拉回路第一题TVT 本题的一个小技巧在于: [建立一个存放点与边关系的邻接矩阵] 1.先判断是否存在欧拉路径 无向图: 欧拉回路:连通 + 所有定点的度为偶数 欧拉路径:连通 + 除源点和终点外都为偶数 有向图: 欧拉回路:连通 + 所有点的入度 == 出度 欧拉路径:连通 + 源点 出度-入度=1 && 终点 入度 - 出度 = 1 && 其余点 入度 == 出度: 2.求欧拉路径 : step 1:选取起点(如果是点的度数全为偶数任意点为S如果有两个点的度数位奇数取一

寒假集训日志(二)——最小生成树,拓扑排序,欧拉回路,连通路

今天学的内容挺多的. (一)首先说最小生成树,两种算法: 1.Kruskal算法( 将边排序,然后再选,关键在于检查是否连通,使用并查集) 2.Prim算法(使用点集,有点类似与最短路的算法) 第一题是并查集算法的使用: A - The Suspects Time Limit:1000MS     Memory Limit:20000KB     64bit IO Format:%I64d & %I64u Submit Status Description 严重急性呼吸系统综合症( SARS),