题意:一张多米诺骨牌正反两面各有一个数字,给定n个骨牌以及其上的数字,问是否有骨牌的一个排列,使得相邻骨牌相对位置的数字相同。其中骨牌可以旋转180度。如果有,则给出一种排列方式。‘+’表示骨牌不易向,‘-’则表示需要易向。
思路:求欧拉路径。其中判断连通与否和找欧拉路径的工作可以放到一个dfs中去。
poj 2230题意:给定一个无向图,求从点1开始,经过每条边恰好两次,且两次必须逆向经过这条边的走法。题目保证有解。实际上就是有向图的欧拉回路问题,边里加上一个判断变量即可。
#include <stdio.h>
#include <string.h>
#define N 7
int n,res=0;
int map[N][N],degree[N];
struct edge{
int x,y;
}e[105],s[105];//e数组用来保存边;s数组用来记录欧拉通路(回路)
void dfs(int i){//寻找欧拉通路!!!
int j;
for(j = 0;j<=6;j++)
if(map[i][j]){
map[i][j]--;map[j][i]--;
dfs(j);
s[res].x = j;
s[res++].y = i;
}
}
int main(){
int begin,i,j,num,a,b;
freopen("a.txt","r",stdin);
scanf("%d",&n);
memset(map,0,sizeof(map));
for(i = 1;i<=n;i++){
scanf("%d %d",&a,&b);
map[a][b]++; map[b][a]++;
degree[a]++; degree[b]++;
e[i].x = a;e[i].y = b;
}
for(i = num = 0,begin=e[1].x;i<=6;i++)//begin的初始化是为了所有顶点都是偶数度时考虑
if(degree[i] & 1){
begin = i;
num ++;
}
if(num > 2)//奇数顶点大于2,必无欧拉通路
printf("No solution\n");
else{
dfs(begin);//寻找欧拉回路
if(res < n)//连通分量多于一个
printf("No solution\n");
else
for(i = 0;i<n;i++)
for(j = 1;j<=n;j++){//与输入边比较,判断是否需要反向
if(s[i].x==e[j].x&&s[i].y==e[j].y){
printf("%d +\n",j);
e[j].x = -1;//保证每边只用一次
break;
}else if(s[i].x==e[j].y&&s[i].y==e[j].x){
printf("%d -\n",j);
e[j].x = -1;
break;
}
}
}
return 0;
}
poj 2230:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <cstdlib>
using namespace std;
#define clc(s,t) memset(s,t,sizeof(s))
#define INF 0x3fffffff
#define N 50005
struct edge{
int y,flag,next;
}e[N<<1];
int first[N],top;
int n,m;
void add(int x,int y){
e[top].y = y;
e[top].next = first[x];
e[top].flag = 0;
first[x] = top++;
}
void dfs(int x){
int i;
for(i = first[x];i!=-1;i=e[i].next){
if(!e[i].flag){
e[i].flag = 1;
dfs(e[i].y);
}
}
printf("%d\n",x);
}
int main(){
int i,a,b;
clc(first, -1);
scanf("%d %d",&n,&m);
for(i = 1;i<=m;i++){
scanf("%d %d",&a,&b);
add(a,b);
add(b,a);
}
dfs(1);
return 0;
}