您的位置:首页 > 其它

sgu 101 Domino (欧拉路)

2014-10-04 19:22 281 查看
题目链接:http://acm.sgu.ru/problem.php?contest=0&problem=101

思路: 最裸的欧拉路的题目 把骨牌的每一面当成点 每一张骨牌的两面都建一条无向边 求出此图的一条欧拉路即可。

在此总结一下欧拉路的知识:

无向图的欧拉路的存在判定: 为连通图 度数为奇数的点的个数为0 or 2

欧拉路的输出:

1.度数为奇数的点的个数为0(此图存在欧拉回路) 任选一点 用dfs入栈记录 最后再倒着输出即可

2.度数为奇数的点的个数为2(非欧拉图) 选出度数为奇数的点 然后再进行dfs

代码中并查集的判联通部分可以用dfs代替

code:

#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>
using namespace std;

const int maxn=10500;
const int maxe=10500;

struct edge
{
int to,next,flag;
} G[maxe];

int head[maxn],si,du[maxn],way[maxe];
int cnt,nn;
bool vis[10];

void add_edge(int s,int t)
{
G[si].flag=true;
G[si].to=t;
G[si].next=head[s];
head[s]=si++;
G[si].flag=true;
G[si].to=s;
G[si].next=head[t];
head[t]=si++;
}

int par[maxn],num[maxn];
void init(int n_)
{
for(int i=0;i<=n_;i++){
par[i]=i;
num[i]=1;
}
}
int Find(int x)
{
if(x==par[x]) return x;
return par[x]=Find(par[x]);
}
void unite(int x,int y)
{
x=Find(x);
y=Find(y);
if(num[x]<num[y]){
par[x]=y;
num[y]+=num[x];
}
else{
par[y]=x;
num[x]+=num[y];
}
}
bool same(int x,int y)
{
return Find(x)==Find(y);
}

void dfs(int vv,int tt)
{
for(int i=head[vv];i!=-1;i=G[i].next){
if(!G[i].flag) continue;
G[i].flag=G[i^1].flag=false;
dfs(G[i].to,i);
}
if(tt!=-1) way[cnt++]=tt;
}

void output(int kk)
{
cnt=0;
if(kk==0){
for(int i=0;i<=6;i++){
if(!vis[i]) continue;
dfs(i,-1);
break;
}
}
else{
for(int i=0;i<=6;i++){
if(!vis[i]) continue;
if(du[i]%2!=0){
dfs(i,-1);
break;
}
}
}
for(int i=cnt-1;i>=0;i--){
if(way[i]%2) printf("%d -\n",way[i]/2+1);
else         printf("%d +\n",way[i]/2+1);
}
}

int main()
{
int N,s,t,cnt1,cnt2,nn;
bool mark;
while(scanf("%d",&N)!=EOF){
init(N);
nn=0;
memset(vis,0,sizeof(vis));
memset(du,0,sizeof(du));
memset(head,-1,sizeof(head));
si=0;
for(int kk=0;kk<N;kk++){
scanf("%d%d",&s,&t);
add_edge(s,t);
du[s]++;
du[t]++;
if(!same(s,t))  unite(s,t);
vis[s]=vis[t]=true;
}
for(int i=0;i<=6;i++) if(vis[i]) nn++;
mark=0;
for(int i=0;i<=6;i++){
if(!vis[i]) continue;
if(num[Find(i)]!=nn){
printf("No solution\n");
mark=1;
}
break;
}
if(mark==1) continue;
cnt1=cnt2=0;
for(int i=0;i<=6;i++){
if(!vis[i]) continue;
if(du[i]%2==0) cnt1++;
else cnt2++;
}
if(cnt2==0) output(0);
else if(cnt2==2) output(1);
else printf("No solution\n");
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: