sgu 101/poj 2230欧拉路

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


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值