您的位置:首页 > 其它

POJ 1386 Play on Words(判断欧拉回路存在)

2010-07-27 19:48 447 查看
//求欧拉回路,注意欧拉图的性质
//构图的思想是以单词的首字母和末字母作为结点构图,将单词作为一条有向边
//(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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: