UVA 10129 Play on Words(欧拉道路)

题意:给你n个字符串,问你是否可以出现一条链,保证链中每个字符串的第一个元素与上一个字符串的最后一个元素相同,注意可能重复出现同一个字符串

 

题解:以每一个字符串第一个元素指向最后一个元素形成一个有向图,判断这个有向图是否可以形成欧拉路就好

   注意可能有重边与自环,因此求欧拉路时判断的是是否使用完了所有的边,求起点时注意出度与入度的计算

   欧拉道路是从一个点一笔画完整张图(欧拉回路保证回到起点),注意除了起点与终点以外所有的点出度入度相等

   起点出度大入度1,终点相反(所有的点出入度相等也可以),根据这个情况求到起点

   接着使用dfs直接遍历所有的边,遍历一次记录一次就好了

 

#include<cstdio>
#include<cstring>
const int Max=50;
int graph[Max][Max],vis[Max][Max];
int startPoint(int n)//找欧拉路的起点,注意所有点出入度都相等的问题
{
    int res=0,mark=0;
    for(int i=0; i<n; ++i)
    {
        int out=0,in=0;//入度,出度
        for(int j=0; j<n; ++j)
        {
            out+=graph[i][j];
            in+=graph[j][i];
        }
        if(out-in==1)//中间每个点出入度一样,起点出度比入度大一,终点相反
            return i;
        if(out!=in&&in-out!=1)
            return -1;
    }
    return res;
}
int euler(int u,int n)//求欧拉有向图的道路
{
    int res=0;
    for(int v=0; v<n; ++v)
    {
        if(graph[u][v]&&vis[u][v]<graph[u][v])
        {
            vis[u][v]++;
            res+=euler(v,n);
            res++;
        }
    }
    return res;
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        memset(graph,0,sizeof(graph));
        memset(vis,0,sizeof(vis));
        int n;
        scanf("%d",&n);
        for(int i=0; i<n; ++i)
        {
            char str[1010];
            scanf("%s",str);
            graph[str[0]-'a'][str[strlen(str)-1]-'a']++;
        }
        int u=startPoint(26);//printf("%d\n",u);
        if(u>=0&&euler(u,26)==n)
        {
            printf("Ordering is possible.\n");
        }
        else
        {
            printf("The door cannot be opened.\n");
        }
    }
}

 

posted @ 2017-04-25 21:30  专注如一  阅读(196)  评论(0编辑  收藏  举报