题目链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=230
解题思路:将信息用一个无向图表示。将每一个彩色棒进行编号,如果可以连在一起,那么两个节点之间就有一条边,
最后题目就变成了这个无向图是否单连通并具有欧拉路。
单连通性使用并查集即可;欧拉路只需每个节点的度为偶数或者度为奇数的节点数量为2。
代码附上:
#include<iostream>
#include<map>
#include<string>
#include<cstring>
using namespace std;
int pre[500002];
bool degree[500002];
int find(int x) {
if(pre[x] == -1) return x;
return pre[x] = find(pre[x]);
}
void Union(int x, int y) {
int tx = find(x);
int ty = find(y);
if(tx != ty) pre[ty] = tx;
}
int main() {
freopen("data.in", "r", stdin);
map<string, int> ma;
string s1, s2;
int k, n, cur;
scanf("%d", &k);
while(k--) {
scanf("%d", &n);
if(n == 0) {
printf("Possible\n");
continue;
}
cur = 1; ma.clear();
memset(pre, -1, sizeof(pre));
memset(degree, 0, sizeof(degree));
for(int i = 0; i < n; i++) {
cin>>s1>>s2;
if(ma[s1] == 0) ma[s1] = cur++;
degree[ma[s1]] = !degree[ma[s1]];
if(ma[s2] == 0) ma[s2] = cur++;
degree[ma[s2]] = !degree[ma[s2]];
Union(cur-2, cur-1);
}
int cnt = 0, sum = 0;
for(int i = 1; i < cur; i++) {
if(pre[i] == -1) cnt++;
if(degree[i]) sum++;
}
if(cnt == 1 && (sum == 0 || sum == 2))
printf("Possible\n");
else printf("Impossible\n"),printf("%d %d\n", cnt, sum);
}
return 0;
}