UVa10129 - Play on Words

题意:n个单词形成序列,能够使每一个单词的第一个字母和上一个单词的最后一个字母相同

分析:意即是否形成欧拉道路,所以先以每个单词的首、尾形成点,连成有向边构图。

  形成欧拉道路有2个条件:

    1.图连通

    2.图中所有点的出度`等于`入度,或只有两个奇度点并且一个点的入度比出度大1(终点),另一个点的出度比入度大1(起点)。

    对于1:dfs判之。2 统计出入度情况判之

#include <cstdio>
#include <cstring>
using namespace std;

const int maxn = 100;

int T, n, G[maxn][maxn], c[maxn], in[maxn], out[maxn];
int vis[maxn];

void dfs(int u)
{
    vis[u] = 1;                //访问标记
    for (int v =0; v < 26; v++)       //字母节点
        if (!vis[v] && G[u][v]) dfs(v);  //没有被访问并且有有向边
}

int main()
{
    char s[2000];
    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);

        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;         //有有向边
            in[t]++;out[r]++;          //很重要!!!,出入度别写反了,
            vis[r] = vis[t] = 0;    //将其置为未访问状态
        }
        int flag = 0;
        int p = 0, cnt1 = 0, cnt2 =0, cnt3 = 0;
        for (int i = 0; i < 26; i++) {
                if (out[i] == in[i])
                    continue;      //环的情况
                if (out[i] == in[i]+1) {
                    cnt1++;p = i;    //起始点
                } else if (in[i] == out[i] + 1)
                    cnt2++;        //其余点
                else
                    cnt3++;       //没有满足
        }
        if (cnt3 > 0) {
            printf("The door cannot be opened.\n");
            continue;
        }
     // 环或者是
if (cnt1==1 &&cnt2 == 1 || cnt1==0 && cnt2==0) flag = 1; else flag = 0; dfs(p); for (int i = 0; i < 26; i++) if(!vis[i]) flag = 0; if (flag) printf("Ordering is possible.\n"); else printf("The door cannot be opened.\n"); } return 0; }

ps: 一些细节没注意,debug了很久,也参照了别人的代码,要加油!!!T^T。。。

posted @ 2017-03-21 19:42  hzsai  阅读(1309)  评论(1编辑  收藏  举报