【问题描述】
我妹妹有一条彩色的漂亮项链。如下图所示,项链中每两个相邻珠子的接触点颜色相同。
突然有一天,项链断掉了,所有珠子都散开了,滚得到处都是。妹妹找到了所有她能找到的珠子,但是她无法确定是否把珠子都找齐了。她想知道,只用那些已经找到的珠子是否可以穿出一条据有相同特点的项链。如果可以的话,应怎样安排这些珠子的顺序?
写一个程序来解决这个问题。
【输入格式】
有T组测试数据,每组数据的第一行是一个整数 N(5<=N<=1000),表示珠子的个数。接下来的 N 行每行包含两个整数,即珠子两半的颜色。颜色用 1~50 的整数来表示。
【输出格式】
对于每组数据,输出测试数据编号和方案。
如果无解,输出 “some beads may be lost”。
方案的格式和输入相同,也是一共 N 行,每行用两个整数描述一个珠子(从左到右顺序),其中第一个整数表示左半边颜色,第二个整数表示右半边的颜色。根据题目规定,对于 1<=i<=N-1,第 i 行的第二个数必须等于第 i+1 行上的第一个数,且第 N 行的第二个数必须等于第一行的第一个数(因为项链是环形的)。则如果有多组解,输出第一列字典序最小的。
相邻两个数据之间应输出一个空行。
【输入样例】
2
5
1 2
2 3
3 4
4 5
5 6
5
2 1
2 2
3 4
3 1
2 4
【输出样例】
Case #1
some beads may be lost
Case #2
1 2
2 2
2 4
4 3
3 1
【数据范围】
5<=N<=1000
这道题实质上是无向欧拉回路问题,要判断两个条件,一是每个点的度都为偶数,二是图要基连通。满足以上两个条件就可以输出答案。用邻接矩阵比邻接表方便很多。
#include<stdio.h>
#include<string.h>
#include<vector>
#include<algorithm>
using namespace std;
const int maxn=1002;
int T,n,s=maxn,cnt=0,g[52][52],vis[2*maxn],d[maxn];
vector<int>e;
void dfs(int i)
{
for(int j=1;j<=50;j++)
{
if(g[i][j])
{
g[i][j]--;
g[j][i]--;
dfs(j);
}
}
e.push_back(i);
}
bool check()
{
for(int i=1;i<=n;i++)
{
if(d[i]%2) return 0;
}
memset(vis,0,sizeof(vis));
dfs(s);
if(e.size()!=n+1||e[0]!=s) return 0;
return 1;
}
int main()
{
//freopen("1.txt","r",stdin);
scanf("%d",&T);
for(int k=1;k<=T;k++)
{
scanf("%d",&n);
memset(g,0,sizeof(g));
memset(d,0,sizeof(d));
e.clear();
s=maxn;
int x,y;
for(int i=1;i<=n;i++)
{
scanf("%d %d",&x,&y);
g[x][y]++,g[y][x]++,d[x]++,d[y]++;
s=min(s,x),s=min(s,y);
}
printf("Case #%d\n",k);
if(check())
{
for(int i=e.size()-1;i>0;i--)
{
printf("%d %d\n",e[i],e[i-1]);
}
}
else printf("some beads may be lost\n");
printf("\n");
}
return 0;
}