地目地址:http://acm.hdu.edu.cn/showproblem.php?pid=1116
题意给出n个字符串,第一个字符串最后一个字符与第二个字符串的第一个字符相同,则这两个字符串可以连起来。
要你判断仅用一次所有的字符串,是否能构成一条链或者一个环。
用并查集判断是不是一个连通,然后再判断是不是链或环。
代码如下:
#include <iostream>
#include <vector>
#include <list>
#include <deque>
#include <queue>
#include <iterator>
#include <stack>
#include <map>
#include <set>
#include <algorithm>
#include <cctype>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <cmath>
using namespace std;
const int N=10001;
typedef long long LL;
int parent[33],in[33],out[33];
char s[1010];
void build(int n)
{
for(int i=1;i<=n;i++)
parent[i]=i;
}
int find(int x)
{
int r = x;
while (parent[r] != r) //循环结束,则找到根节点
r = parent[r];
int i = x;
while (i != r) //本循环修改查找路径中所有节点
{
int j = parent[i];
parent[i] = r;
i = j;
}
return r;
}
void uniou(int x,int y)
{
x=find(x);
y=find(y);
if(x==y)return;
parent[x]=y;
}
bool isnot()
{
int i,sum=0;
for(i=1;i<=26;i++)
if((in[i]||out[i])&&parent[i]==i)//i存在,且parent[i]==i,一个连通
sum++;
if(sum!=1)
return true;
return false;
}
int main()
{
int i,j,T;
cin>>T;
while(T--)
{
int t;
cin>>t;
memset(in,0,sizeof(in));
memset(out,0,sizeof(out));
build(26);
while(t--)
{
scanf("%s",s);
int len=strlen(s);
int a,b;
a=s[0]-'a'+1;
b=s[len-1]-'a'+1;
out[a]++;
in[b]++;
uniou(a,b);
}
//首先判断是不是一个连通图
if(isnot())
{
printf("The door cannot be opened.\n");
continue;
}
//判断是不是一个环或者一条链
int f1=0,f2=0,f3=0;
for(i=1;i<=26;i++)
{
if(in[i]-out[i]==1) f1++;
if(in[i]-out[i]==-1) f2++;
if(in[i]-out[i]==0) f3++;
}
//(f1+f2+f3)==26必须加上去
if((f1==1&&f2==1||f1==0&&f2==0)&&(f1+f2+f3)==26)
printf("Ordering is possible.\n");
else
printf("The door cannot be opened.\n");
}
return 0;
}