欧拉回路
无向图 | 有向图 | |
---|---|---|
欧拉回路 | 所有点均为偶度顶点(顶点度数为偶数) | 所有点出度=入度(入度=箭头射入个数) |
欧拉通路 | 最多仅2个点为奇度顶点(顶点度数为奇数) | 最多两个点出度!=入度;其中一个出度比入度大1;另一个入度比出度大1 |
uva 1030
除了起点和终点以外,其他的点“进出”次数相等。
即一个无向图是连通的,且最多只有两个奇点,一定存在欧拉回路
// 坑:为一个环状时 形成欧拉回路tmp为26
//
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int G[30][30];// 26 个小写字母
int vis[26];
int out[26];
int in[26];
void dfs(int u){ // u
vis[u]= 1; // 标记起始量已访问
for(int v=0;v<26;v++){
if((G[u][v]||G[v][u])&&vis[v]==0){
dfs(v);
}
}
return ;
}
// 判断是否无向图联通 思路:
//先访问存在的点
bool iscircle(){
int tmp=0;
for(int i=0;i<26;i++)
for(int j=0;j<26;j++){
if(G[i][j]){
if(tmp==0) {
dfs(i);
tmp=1;
} else{
if(!vis[i]||!vis[j]) //如果点i或者j未被访问
return false;
}
}
}
return true;
}
// 判断是否无向图联通 思路:
//先访问存在的点
int main(){
//1.处理输入输出 输入为有向图
//2.判断无向图联通
//3. 判断入度数和出度是否相同 最多两个不同
char c[1005];
// freopen("10129.txt","r",stdin);
int t;
cin>>t;
while(t--){
memset(G,0,sizeof(G));
int n;
cin>>n;
memset(out,0,sizeof(out));
memset(in,0,sizeof(in));
memset(vis,0,sizeof(vis)) ;
for(int i=0;i<n;i++){
scanf("%s",c);
int v=c[strlen(c)-1]-'a';
int u=c[0]-'a';
G[u][v] ++;
out[v]++;
in[u]++;
}
int tmp1=0,tmp2=0,tmp=0;
// tmp1 出度比入度大一
// tmp2 入度比出度大一
// tmp 为入度等于出度的个数
for(int i =0;i<26;i++){
if(out[i]==in[i])
tmp ++;
if(out[i]==in[i]+1){// 出度比入度大一
tmp1++;
}else if(out[i]+1==in[i]){// 入度比出度大一
tmp2++;
}
}
if((tmp==26-2&&tmp1==1&&tmp2==1)||tmp==26&&iscircle()){ // 要考虑成环的情况
cout<<"Ordering is possible.\n";
}else{
cout<<"The door cannot be opened.\n";
}
}
return 0;
}
//另一种思路通过读入度 来判断连通性
// 上面通过双向判断dfs联通G[u][v] 和G[v][u]
void dfs(int u){ // u
vis[u]= 1; // 标记起始量已访问
for(int v=0;v<26;v++){
if(G[u][v]&&vis[v]==0){
dfs(v);
}
}
return ;
}
for(int j=0;j<26;j++)
if(in[j]){
dfs(j);break;
}
int flag2=1;
for(int i=0;i<26;i++)
{
if(in[i]&&!vis[i]){
flag2=0;break;
}
if(out[i]&&!vis[i]){
flag2=0;break;
}
}
//
if((tmp==26-2&&tmp1==1&&tmp2==1)||tmp==26&&flag2==1){
cout<<"Ordering is possible.\n";
}else{
cout<<"The door cannot be opened.\n";
}