题意:一张多米诺骨牌正反两面各有一个数字,给定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; }