并查集求欧拉回路/通路

来源:互联网 发布:淘宝线下实体店加盟费 编辑:程序博客网 时间:2024/05/01 15:08

题目:http://acm.hdu.edu.cn/showproblem.php?pid=1116


题意:给你一些英文单词,判断所有单词能不能连成一串,类似成语接龙。但是如果有多个重复的单词时,也必须满足这样的条件才能算YES。否则都是不可能的情况。


分析:我们以每个单词的首尾为节点建立有向图,然后再判断这个图是否是欧拉通路或者是欧拉回路就行了。当然用并查集判断。



那么先了解概念:


欧拉通路:除首尾结点外,其余结点入度等于出度,起点出度减入度等于1,终点入度减出度等于1。

欧拉回路:所有结点的入度都等于出度。


#include <iostream>#include <string.h>#include <stdio.h>using namespace std;const int N = 26;int pre[N];int IN[N],OT[N],p[N];bool vis[N];char str[1005];void Init(){    memset(vis,0,sizeof(vis));    memset(IN,0,sizeof(IN));    memset(OT,0,sizeof(OT));    for(int i=0;i<N;i++)        pre[i] = i;}int Find(int x){    if(pre[x] != x)        pre[x] = Find(pre[x]);    return pre[x];}void Union(int x,int y){    x = Find(x);    y = Find(y);    if(x == y) return;    pre[x] = y;}int main(){    int T,n;    scanf("%d",&T);    while(T--)    {        Init();        scanf("%d",&n);        while(n--)        {            scanf("%s",str);            int len = strlen(str);            int x = str[0] - 'a';            int y = str[len-1] - 'a';            Union(x,y);            OT[x]++;            IN[y]++;            vis[x] = vis[y] = 1;        }        int cnt = 0;        for(int i=0;i<N;i++)        {            pre[i] = Find(i);            if(vis[i] && pre[i]==i)                cnt++;        }        if(cnt > 1)        {            puts("The door cannot be opened.");            continue;        }        int k = 0;        for(int i=0;i<N;i++)        {            if(vis[i] && IN[i] != OT[i])                p[k++] = i;        }        if(k == 0)        {            puts("Ordering is possible.");            continue;        }        if(k == 2 && ((OT[p[0]] - IN[p[0]] == 1 && IN[p[1]] - OT[p[1]] == 1) || (OT[p[1]] - IN[p[1]] == 1 && IN[p[0]] - OT[p[0]] == 1)))        {            puts("Ordering is possible.");            continue;        }        puts("The door cannot be opened.");    }    return 0;}



原创粉丝点击