poj 1386 判断欧拉图存在
网上转载,有点偷懒
//求欧拉回路,注意欧拉图的性质
//构图的思想是以单词的首字母和末字母作为结点构图,将单词作为一条有向边
//(A)----acm------>(M)-----malform---->(M)------mouse----->(E)
//1、第一步是要先对图的连通性进行判断,即去掉边的方向,看图是否连通
//我看了数据规模才26,我就偷懒写个Floyd水下算了
//2、第二步就是根据欧拉图的性质进行判断就可以了,判断存在欧拉道路或存在欧拉回路
//(1)有向图G为欧拉图(存在欧拉回路),当且仅当G的基图连通,且所有顶点的入度等于出度。
//(2)有向图G为半欧拉图(存在欧拉道路),当且仅当G的基图连通,且存在顶点u的入度比出度大1、v的入度比出度小1,其它所有顶点的入度等于出度。
#include<iostream>
#include<vector>
using namespace std;
int indeg[26],outdeg[26],vis[26];
int G[26][26];
char word[1010];
vector<int> letter;
int t,m;
bool checkEulerPath()
{
int st,ed;
st = ed = 0;
bool circle = 1;
for(int i = 0;i < letter.size();++i)
{
int x = letter[i];
if(indeg[x] - outdeg[x] == 1)
{
++ed;
circle = 0;
}
else if(outdeg[x] - indeg[x] == 1)
{
++st;
circle = 0;
}
else if(outdeg[x] != indeg[x]) return false;
}
if(circle) return true;
if(st == 1 && ed == 1) return true;
return false;
}
void Floyd()
{
for(int k = 0;k < 26;++k)
for(int i = 0;i < 26;++i)
for(int j = 0;j < 26;++j)
if(G[i][k] && G[k][j])
G[i][j] = 1;
}
bool checkConnect()
{
Floyd();
for(int i = 0;i < letter.size();++i)
for(int j = 0;j < letter.size();++j)
{
int x = letter[i];
int y = letter[j];
if(!G[x][y]) return false;
}
return true;
}
int main()
{
//freopen("in.txt","r",stdin);
scanf("%d",&t);
while(t--)
{
scanf("%d",&m);
letter.clear();
memset(indeg,0,sizeof(indeg));
memset(outdeg,0,sizeof(outdeg));
memset(G,0,sizeof(G));
memset(vis,0,sizeof(vis));
while(m--)
{
scanf("%s",word);
int last = word[strlen(word) - 1] - 'a';
int first = word[0] - 'a';
G[first][last] = G[last][first] = 1;
indeg[last]++;
outdeg[first]++;
if(!vis[last])
{
letter.push_back(last);
vis[last] = 1;
}
if(!vis[first])
{
letter.push_back(first);
vis[first] = 1;
}
}
if(checkConnect() && checkEulerPath())
printf("Ordering is possible.\n");
else
printf("The door cannot be opened.\n");
}
return 0;
}
浙公网安备 33010602011771号