POJ 2337 输出欧拉路径

太无语了。

这道题做了一整天。

主要还是我太弱了。

以后这个就当输出欧拉路径的模版吧。

题目中的输出字典序最小我有点搞不清楚,看了别人是这么写的。但是我发现我过不了后面DISCUSS里面的数据。

题意理解问题还是题目问题?

这道题大致以下分几步吧。

判断图是否连通,用并查集判断即可。

判断图是否有欧拉回路或者通路,判断出度和入度即可,若是欧拉通路,找出起点。

DFS找出欧拉路径输出。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string>
#include <cmath>
#include <cstring>
#include <queue>
#include <set>
#include <vector>
#include <stack>
#include <map>
#include <iomanip>
#define PI acos(-1.0)
#define Max 2505
#define inf 1<<28
#define LL(x) ( x << 1 )
#define RR(x) ( x << 1 | 1 )
#define REP(i,s,t) for( int i = ( s ) ; i <= ( t ) ; ++ i )
#define ll long long
#define mem(a,b) memset(a,b,sizeof(a))
#define mp(a,b) make_pair(a,b)
#define PII pair<int,int>
#define N 10005
using namespace std;

inline void RD(int &ret) {
    char c;
    do {
        c = getchar();
    } while(c < '0' || c > '9') ;
    ret = c - '0';
    while((c=getchar()) >= '0' && c <= '9')
        ret = ret * 10 + ( c - '0' );
}
inline void OT(int a) {
    if(a >= 10)OT(a / 10) ;
    putchar(a % 10 + '0') ;
}

char a[N] ;
vector<string>g[300] ;
int in[N] ,out[N] ;
int vis[N] ;
int f[N] ;
int n ;
int first ;

int find(int x) {
    return f[x] == x ? x : f[x] = find(f[x]) ;
}

void Union(int a ,int b) {
    a = find(a) ;
    b = find(b) ;
    if(a == b)return ;
    if(a > b)f[a] = b ;
    else f[b] = a ;
}

void init() {
    mem(in , 0) ;
    mem(out ,0) ;
    for (int i = 0 ; i < 260 ; i ++ )f[i] = i ;
    for (int i = 0 ; i < 260 ; i ++ )g[i].clear() ;
    first = 0 ;
    mem(vis, 0) ;
}

stack<string>ans ;
void dfs(int now ){
    int sz = g[now].size() ;
    while(g[now].size() > 0){
        string nn = g[now][0] ;
        int tt = g[now][0][g[now][0].size() - 1] - 'a' ;
        g[now].erase(g[now].begin()) ;
        dfs(tt) ;
        ans.push(nn) ;
    }
}
int main() {
    int T ;
#ifndef ONLINE_JUDGE
    freopen("D:\\acm.txt","r",stdin) ;
#endif
    cin >> T ;
    while(T -- ) {
        cin >> n ;
        init() ;
        for (int i = 1 ; i <= n ; i ++ ) {
            scanf("%s",a) ;
            int s = a[0] - 'a' ;
            int e = a[strlen(a) - 1] - 'a' ;
            out[s] ++ ;
            in[e] ++ ;
            g[s].push_back(a) ;
            Union(s , e) ;
            vis[s] = vis[e] = 1 ;
        }
        int fnum = 0 ;
        int dnum = 0 ;
        bool flag = 0 ;
        int st = -1 ;
        for (int i = 0 ; i < 26 ; i ++ ) {
            if(!vis[i])continue ;
            if(i == find(i))fnum ++ ;
            if(in[i] - out[i] == 1){
                dnum ++ ;
            }
            if(out[i] - in[i] == 1){
                dnum ++ ;
                st = i ;
            }
            if(abs(out[i] - in[i]) >= 2){
                flag = 1 ;
            }
        }
        if((dnum == 1 || dnum > 2) ||(flag) || (fnum != 1)) {
            puts("***") ;
            continue ;
        }
        else{
            for (int i = 0 ;i < 26; i ++ ){
                if(st == -1 && vis[i])st = i ;//如果是欧拉回路,则找到字典序最小的起点。
                sort(g[i].begin() , g[i].end()) ;
            }
            while(!ans.empty())ans.pop() ;
            dfs(st) ;
            printf("%s",ans.top().c_str()) ;
            ans.pop() ;
            while(!ans.empty()){
                printf(".%s",ans.top().c_str()) ;
                ans.pop() ;
            }
            puts("") ;
        }
    }
    return 0 ;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值