您的位置:首页 > 其它

uva10129

2016-04-10 10:04 381 查看
题目描述:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=19492

/*1:通常想法是将每个单词看成一个节点,但如果单词的尾部与另外一个单词的首部相同,就能架起一座“桥”,但这样以来,数组就开太大了
2:将每个单词的首尾两个字母看成节点,此时单词就是一座桥。这样就可以根据欧拉道路的出入度来判断
3:注意题中判断欧拉道路的起点以及终点的技巧*/
#include <cstdio>
#include <cstring>
#include <iostream>
#include <string>

using namespace std;
const int maxc = 1000 + 5;

int n, in[30], out[30], graph[30][30], start, visit[30];    //从start这个点开始dfs

void dfs(int u) {
visit[u] = 1;
for(int v = 0; v < 26; v++) {
if(graph[u][v] > 0) {   //因为节点可以重复,所以不能在条件里加上 && !visit[v]
graph[u][v]--;      graph[v][u]--;
dfs(v);
}
}
}

bool isConnected() {
memset(visit, 0, sizeof(visit));
dfs(start);
for(int i = 0; i < 26; i++)
if(in[i] + out[i])  //出入度为0的字母没有出现过,此时不计
if(!visit[i])   return false;
return true;
}

bool solve() {
if(!isConnected())  return false;

int theBegin = 0, theEnd = 0;
for(int u = 0; u < 26; u++) {
if(in[u] != out[u]) {
if(!theBegin && out[u] - in[u] == 1)    theBegin = 1;
else if(!theEnd && in[u] - out[u] == 1)     theEnd = 1;
else return false;
}
}
return true;
}

int main() {
int kase;
scanf("%d", &kase);
while(kase--) {
scanf("%d", &n);

//初始化
memset(in, 0, sizeof(in));
memset(out, 0, sizeof(out));
memset(graph, 0, sizeof(graph));

//输入同时确定出度以及入度
string str;
for(int i = 0; i < n; i++) {
cin >> str;
int u = str[0] - 'a';   int v = str[str.length() - 1] - 'a';
out[u]++;   in[v]++;
graph[u][v]++;  graph[v][u]++;//注意虽然是有向图,但这行代码这样写的目地是为了dfs能够顺利遍历整张图,不然有些点访问不到
start = u;
}

if(solve())     printf("Ordering is possible.\n");
else              printf("The door cannot be opened.\n");
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: