POJ2337 欧拉路径

题意:给你n个单词,问你能不能形成欧拉路径
欧拉路径和欧拉回路
欧拉路径:从某结点出发一笔画成所经过的路线叫做欧拉路径。
欧拉回路:在欧拉路径的基础上又回到起点。
a、凡是由偶点组成的连通图,一定可以一笔画成。画时可以把任一偶点为起点,最后一定能以这个点为
终点画完此图。   
b、凡是只有两个奇点的连通图(其余都为偶点),一定可以一笔画成。画时必须把一个奇点为起点,另
一个奇点终点。  
c、其他情况的图都不能一笔画出。(有偶数个奇点除以2便可算出此图需几笔画成。)

欧拉回路和欧拉路径的判断
欧拉回路:
无向图:每个顶点的度数都是偶数,则存在欧拉回路。
有向图:每个顶点的入度都等于出度,则存在欧拉回路。
欧拉路径:
无向图:当且仅当该图所有顶点的度数为偶数 或者 除了两个度数为奇数外其余的全是偶数。
有向图:当且仅当该图所有顶点 出度=入度 或者 一个顶点 出度=入度+1,另一个顶点 入度=出度+1,其
他顶点 出度=入度。

判断完欧拉路径后,则可以用fleury算法输出路径

#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <queue>
#include <map>
#include <iostream>
#include <cmath>
#define INF 0x3f3f3f3f
using namespace std;
string s[1005];
int out[26],in[26],cnt;
int ans[1005],head[30];
struct node
{
    int nxt,to,id,vv;
}edge[2010];
void add(int u,int v,int id)
{
    edge[++cnt].to=v;
    edge[cnt].nxt=head[u];
    head[u]=cnt;
    edge[cnt].id=id;
    edge[cnt].vv=0;
}
void dfs(int u)
{
    for(int i=head[u];~i;i=edge[i].nxt)
        if(!edge[i].vv)
        {
            edge[i].vv=1;
            dfs(edge[i].to);//回溯来记录
            ans[cnt++]=edge[i].id;
        }
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n;
        scanf("%d",&n);
        memset(out,0,sizeof(out));
        memset(in,0,sizeof(in));
        memset(head,-1,sizeof(head));
        for(int i=0; i<n; i++)
        {
            cin>>s[i];
            in[s[i][0]-'a']++;
            out[s[i][s[i].length()-1]-'a']++;
        }
        int c1=0,c2=0,st=100;
        for(int i=0;i<26;i++)
        {
            if(in[i]-out[i]==1)
                c1++,st=i;
            else if(in[i]-out[i]==-1)
                c2++;
            else if(out[i]-in[i]!=0)
                c1=3;
        }
        if(!((c1==0&&c2==0)||(c1==1&&c2==1)))
        {
            puts("***");
            continue;
        }
        sort(s,s+n);
        cnt=0;
        for(int i=n-1; i>=0; i--)
        {
             int u=s[i][0]-'a',v=s[i][s[i].length()-1]-'a';
             add(u,v,i);
             if(c1) continue;
             st=min(st,u);
             st=min(st,v);
        }
        cnt=0;
        dfs(st);

        if(cnt!=n)
            puts("***");
        else
        {
            cout<<s[ans[cnt-1]];
            for(int i=cnt-2;i>=0;i--)
                cout<<"."<<s[ans[i]];
            puts("");
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值