SGU 101 Domino【欧拉路径】

题目链接:

http://acm.sgu.ru/problem.php?contest=0&problem=101

题意:

N个多米诺骨牌,每个骨牌左右两侧分别有一个0~6的整数(骨牌可以旋转以调换其左右两数),求一种把这些骨牌从左到右排列的方案,使得所有相邻的两数字相等(即左边骨牌右侧的数字等于右边骨牌左侧的数字)。

分析:

把数字当成点,骨牌当做边。构成无向图,求一发欧拉道路即可。
无向图求欧拉路径还是很好写的。
欧拉路径深入讲解:http://blog.chinaunix.net/uid-26380419-id-3164913.html

代码:

#include<iostream>
#include<map>
#include<cstring>
#include<stack>
#include<set>
using namespace std;
const int maxn = 200 + 5, maxm = 6 + 5;
struct Edge{int to;int dir; int id;int next;};
int tot = 0;
Edge edge[maxn];
stack<Edge>s;
int pa[maxn], head[maxm], cnt[maxm];
bool vis[maxn];
int _find(int a)
{
    if(a == pa[a]) return a;
    return pa[a] = _find(pa[a]);
}
void unite(int a, int b)
{
    int ra = _find(a);
    int rb = _find(b);
    if(ra == rb) return ;
    pa[rb] = ra;
}
bool same(int a, int b)
{
    return _find(a) == _find(b);
}
void add_edge(int u, int v, int id)
{
    edge[tot].to = v;
    edge[tot].id = id;
    edge[tot].dir = 1;
    edge[tot].next = head[u];
    head[u] = tot++;
    edge[tot].to = u;
    edge[tot].dir = 0;
    edge[tot].id = id;
    edge[tot].next = head[v];
    head[v] = tot++;
}
void dfs(int u)
{
    for(int i = head[u]; i != -1; i = edge[i].next){
        if(!vis[i]){
            vis[i] = true;
            vis[i^1] = true;
            dfs(edge[i].to);
            s.push(edge[i]);
        }
    }
}
int main (void)
{
    int n ;cin>>n;
    memset(head, -1, sizeof(head));
    for(int i = 0; i <= 6; i++) pa[i] = i;
    int a, b;
    for(int i = 0; i < n; i++){
        cin>>a>>b;
        add_edge(a, b, i + 1);
        cnt[a]++;
        cnt[b]++;
        unite(a, b);
    }
    int be = -1;
    int ans = 0;
    for(int i = 0; i <= 6; i++){
        if(cnt[i] & 1){
            ans++;
            if(be == -1) be = i;
        }
    }
    if(ans != 0 && ans != 2) return cout<<"No solution"<<endl, 0;
    for(int i = 0; i <= 6; i++){
        if(cnt[i] &&  be == -1) be = i;
        if(cnt[i] && !same(i, be)){return cout<<"No solution"<<endl, 0;}
    }
    dfs(be);
    while(!s.empty()){
        Edge t = s.top();s.pop();
        cout<<t.id<<' ';
        if(t.dir == 0) cout<<"-"<<endl;
        else cout<<"+"<<endl;
    }
    return 0;
}

你可能感兴趣的:(SGU 101 Domino【欧拉路径】)