Uva10129(DFS搜索+联通集)

题目地址:

https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&category=838&problem=1070&mosmsg=Submission+received+with+ID+21459508

题目分析:

n个单词形成序列,能够使每一个单词的第一个字母和上一个单词的最后一个字母相同,即是否形成欧拉通路,所以先以每个单词的首、尾形成点,连成有向边构图。但需要注意的是:只能存在一个欧拉通路(即一个联通集)!这可以通过递归完一次dfs搜索后,再一次扫描所有单词,判断是否还存在没有访问到的边。

代码如下:

#include <bits/stdc++.h>
using namespace std;

const int maxn = 100;

int T, n, G[maxn][maxn], c[maxn], in[maxn], out[maxn];
int vis[maxn];      //判断边的关系 
char s[1010];

void read_word(){
    for(int i = 0;i < n;i++){
        scanf("%s",s);
        int len = strlen(s);
        int r = s[0] - 'a';     //首字母
        int t = s[len - 1] - 'a';       //尾字母 
        G[r][t] = 1;        //记录边的关系 
        out[r]++;in[t]++;
        vis[r] = vis[t] = 0;        //设置为未访问状态 
    }
}


void dfs(int u){
    vis[u] = 1;     //设置为访问状态 
    for(int v = 0; v < 26;v++)
        if(!vis[v] && G[u][v]) dfs(v);
}

int main(void){
    //freopen("data.out","w",stdout);
    scanf("%d",&T);
    while(T--){
        memset(vis,-1,sizeof(vis)); 
        memset(G,0,sizeof(G));
        memset(in,0,sizeof(in));
        memset(out,0,sizeof(out));
        scanf("%d",&n);
        
        read_word();
        
        int p = 0, begin = 0, tail = 0, cnt = 0;
        
        int flag = 0;
        for(int i = 0;i < 26;i++){
            if(out[i] == in[i]){    //中间节点,则跳过下面的步骤 
                continue;
            }
            if(out[i] == in[i] + 1){    //是起始点 
                begin++;p = i;
            } else if(in[i] == out[i] + 1)      //终止点 
                tail++;
            else
                cnt++;      //入度不等于出度,并且不为起始点或者终止点 
        }
        
        if(cnt > 0){        //如果个别节点 
            cout<<"The door cannot be opened.\n";
            continue;
        }   
        
        if(begin == 1 && tail == 1 || begin == 0 && tail == 0)  //有一个奇度起点与终点,或者全部为偶数度顶点 
            flag = 1;
        else 
            flag = 0;
        
        
        dfs(p);
        //扫描所有字母,判断只有一个联通集
        for(int i = 0;i < 26;i++){
            if(!vis[i]) flag = 0;       //如果还有未访问的联通集 
        }   
        
        if(flag) cout<<"Ordering is possible.\n";
        else cout<<"The door cannot be opened.\n";
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/Western-Trail/p/9169220.html