有向圖的歐拉回路判定問題 poj1386
阿新 • • 發佈:2019-01-22
這個題也卡卡卡,發現自己好粗心,唉.。
有向圖的判定:
統計每個點的出度和入度,
前提是有向圖是連通圖。
1. 如果每個點的出度 = 入度 則存在歐拉回路。
2. 如果有且僅有兩點出度、入度不想等,且這兩個點的出度 - 入度差為1 或 -1.差為1的那個點是尤拉圖的起點,為 -1 的是重點。
這個題先來判斷圖的連通性,用並查集的方法,值得注意的一點是並查集是以點為元素的,所以要開26長度的陣列。
在接下來就是判斷出度和入度了。
#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<cmath>
using namespace std;
const int MAXN = 1e5 + 10;
int father[30];
int _rank[30];
int d1[30]; // 出度
int d2[30]; // 入度
bool h[MAXN]; // 判斷是否出現邊中
void init()
{
for(int i = 1;i <= 26;++i)
{
father[i] = i;
_rank[i] = 0;
}
return ;
}
int _find(int i)
{
int root = i;
int temp = i;
while(father[root] != root)
{
root = father[root];
}
while(father[temp] != root)
{
int t;
t = father[temp];
father[temp] = root;
temp = t;
}
return root;
}
void _union(int x,int y)
{
int root1 = _find(x);
int root2 = _find(y);
if(root1 != root2)
{
if(_rank[root1] > _rank[root2])
{
father[root2] = root1;
}
else
{
father[root1] = root2;
if(_rank[root1] == _rank[root2])
{
_rank[root2]++;
}
}
}
return;
}
struct Edge
{
int u,v;
};
Edge e[MAXN];
int n;
bool tell() // 判斷連通性
{
init();
for(int i = 1;i <= n;++i) // 先進行一邊合併
{
int u = e[i].u;
int v = e[i].v;
if(_find(u) != _find(v))
{
_union(u,v);
}
}
bool flag = 1;
int l= -1;
for(int i = 1;i <= 26;++i) // 在判斷father陣列是否只有一個父親節點
{
if(h[i]) // 將不存在點排除
{
if(l == -1)
{
l = father[i];
}
else
{
if(father[i] != father[l])
{
flag = 0;
}
}
}
}
return flag;
}
int main()
{
int T;
cin >> T;
while(T--)
{
memset(d1,0,sizeof(d1));
memset(d2,0,sizeof(d2));
memset(h,0,sizeof(h));
cin >> n;
string s;
for(int i = 1; i <= n;++i)
{
cin >> s;
e[i].u = s[0] - 'a' + 1;
e[i].v = s[s.size() - 1] - 'a' + 1;
d1[e[i].u]++;
d2[e[i].v]++;
h[e[i].u] = 1;
h[e[i].v] = 1;
}
bool flag = tell();
int a,b,k = 0,t = 0;
if(flag)
{
for(int i = 1;i <= 26;++i)
{
if(d1[i] != d2[i])
{
t = 1;
k++;
if(k == 1)
{
a = i;
}
if(k == 2)
{
b = i;
}
}
}
if(!t)
cout << "Ordering is possible." << endl;
else
{
if(k == 2)
{
if((int )abs(d1[a] - d2[a]) == 1 && (int )abs(d1[b] - d2[b]) == 1)
{
cout << "Ordering is possible." << endl;
}
else
{
cout << "The door cannot be opened." << endl;
}
}
else
{
cout << "The door cannot be opened." << endl;
}
}
}
else
{
cout << "The door cannot be opened." << endl;
}
}
return 0;
}