SGU 101 Domino(欧拉图)
2016-04-14 08:23
295 查看
Description
给定若干(n<=100)多米诺骨牌,每张骨牌两端有一数字(0~6),求一种骨牌排列方式,使得除两端外相邻的两张骨牌所对的数字相同
Input
第一行为一整数n表示骨牌数量,之后n行每行两个整数a和b表示该张骨牌两端的数字
Output
输出一种骨牌的排列方式使得除两端外相邻的两张骨牌所对的数字相同,输出占n行,每行表示从左到右每个位置的骨牌编号,之后+or-表示该张骨牌的方法,+表示按输入顺序放,-表示按输入顺序反向放,如果没有合法方案则输出No solution
Sample Input
5
1 2
2 4
2 4
6 4
2 1
Sample Output
2 -
5 +
1 +
3 +
4 -
Solution
将每张骨牌看作一条边,两端数字看作点,则问题转化为找一条有重边图的欧拉路径,这个dfs整张图,每次标记当前走的边,之后不走标记过的边,回溯序列即为欧拉路径,但是注意此题有一些特殊情况需要判断,首先判断图是否连通,不连通则无解;之后找奇度数端点,如果不存在则欧拉路径一定存在,如果存在两个奇度端点则需选取其中一个为dfs起点,如果存在但不是两个则无解
Code
给定若干(n<=100)多米诺骨牌,每张骨牌两端有一数字(0~6),求一种骨牌排列方式,使得除两端外相邻的两张骨牌所对的数字相同
Input
第一行为一整数n表示骨牌数量,之后n行每行两个整数a和b表示该张骨牌两端的数字
Output
输出一种骨牌的排列方式使得除两端外相邻的两张骨牌所对的数字相同,输出占n行,每行表示从左到右每个位置的骨牌编号,之后+or-表示该张骨牌的方法,+表示按输入顺序放,-表示按输入顺序反向放,如果没有合法方案则输出No solution
Sample Input
5
1 2
2 4
2 4
6 4
2 1
Sample Output
2 -
5 +
1 +
3 +
4 -
Solution
将每张骨牌看作一条边,两端数字看作点,则问题转化为找一条有重边图的欧拉路径,这个dfs整张图,每次标记当前走的边,之后不走标记过的边,回溯序列即为欧拉路径,但是注意此题有一些特殊情况需要判断,首先判断图是否连通,不连通则无解;之后找奇度数端点,如果不存在则欧拉路径一定存在,如果存在两个奇度端点则需选取其中一个为dfs起点,如果存在但不是两个则无解
Code
#include<cstdio> #include<iostream> #include<cstring> #include<vector> using namespace std; #define maxn 222 struct Edge { int to,next,id,dir,flag; }edge[maxn]; int n,fa[maxn],head[maxn],tot,degree[maxn]; vector<int>ans; void init() { tot=0; ans.clear(); memset(fa,-1,sizeof(fa)); memset(head,-1,sizeof(head)); memset(degree,0,sizeof(degree)); } int find(int x) { if(fa[x]==-1)return x; return fa[x]=find(fa[x]); } void unite(int x,int y) { x=find(x),y=find(y); if(x!=y)fa[x]=y; } void add(int u,int v,int id,int dir) { edge[tot].to=v; edge[tot].id=id; edge[tot].dir=dir; edge[tot].flag=0; edge[tot].next=head[u]; head[u]=tot++; } void dfs(int u) { for(int i=head[u];~i;i=edge[i].next) if(!edge[i].flag) { edge[i].flag=1; edge[i^1].flag=1; dfs(edge[i].to); ans.push_back(i); } } int main() { while(~scanf("%d",&n)) { init(); int u,v; for(int i=1;i<=n;i++) { scanf("%d%d",&u,&v); add(u,v,i,0),add(v,u,i,1); degree[u]++,degree[v]++; unite(u,v); } int cnt=0,s=-1,mark=1; for(int i=0;i<=6;i++) { if(degree[i]&1)cnt++; if(degree[i]&&s==-1)s=i; } for(int i=0;i<=6;i++) if(degree[i]&&find(i)!=find(s)) mark=0; if(cnt!=0&&cnt!=2||!mark) { printf("No solution\n"); continue; } if(!cnt)dfs(s); else { for(int i=0;i<=6;i++) if(degree[i]&1) { dfs(i); break; } } for(int i=0;i<ans.size();i++) { printf("%d ",edge[ans[i]].id); if(edge[ans[i]].dir)puts("+"); else puts("-"); } } return 0; }
相关文章推荐
- 定义一个结构体变量,输入数据,输出变量内容。
- 第二周项目三小试循环
- Android 基本控件的使用二(注册许可协议)(CheckBox)
- 第四周项目五(2)-用递归方法求解
- Dom编程
- 武器类
- Struts2+jquary ajax方式返回json并解析
- Java项目打包成可执行的Jar包(FatJar 或 Maven)
- 小代码 在线测试
- 项目1——体验成员函数、友元函数和一般函数的区别
- 第五周时间类
- Android所需的Java基础知识体系图
- SGU 100 A+B(水~)
- SQL查询相关技术-8.SQL操作(设置条件)
- 开发者账号续费
- 自己实现的String类
- 高性能服务器性能影响因素
- python基本数据类型-数字
- 第四周项目5(1)-用递归方法求解
- S5PV210的SD卡启动实战1~2