SGU 101 Domino

来源:互联网 发布:安卓手机游戏编程 编辑:程序博客网 时间:2024/05/01 02:10

题意: 给出n块多米诺骨牌,每块骨牌的左右端点有标号(0~6),现要求把给定的骨牌排成一排,要求相邻骨牌的相邻端点标号相等。按顺序输出摆放好的骨牌和它们是否翻转过。

解法: 以0~6为点,骨牌为边,找欧拉通路。先判图的连通性,再判是否存在欧拉通路,存在就DFS一遍输出答案。

#include <stdio.h>#include <string.h>#include <algorithm>using namespace std;#define REP(i,a,b) for(int i=(a); i<(b); i++)#define clr(a,b) memset(a,b,sizeof(a))typedef long long lld;const int INF = ~0u>>1;int n;const int MAXN = 110;struct Edge {    int v, w, next;    int us;}g[MAXN<<1];int head[7],tot;int ds[7];int fa[7];int ans[MAXN],pa;void dfs(int u) {    for(int p=head[u]; ~p; p=g[p].next) {        if(g[p].us) continue;        g[p].us = g[p^1].us = 1;        dfs(g[p].v);        ans[pa++] = g[p].w;    }}int Find(int x) {    return fa[x] = (fa[x] == x) ? x : Find(fa[x]);}void merge(int a, int b) {    a = Find(a);    b = Find(b);    if(a == b) return ;    fa[a] = b;}void add_edge(int u, int v, int id) {    g[tot].v = v;   g[tot].w = id;    g[tot].next = head[u];  head[u] = tot ++;    g[tot].v = u;   g[tot].w = -id;    g[tot].next = head[v];  head[v] = tot ++;}int main() {    scanf("%d", &n);    clr(head, -1);    REP(i,0,7) fa[i] = i;    int l,r;    REP(i,1,n+1) {        scanf("%d%d", &l, &r);        ds[l] ++;        ds[r] ++;        merge(l,r);        add_edge(l,r,i);    }    int od = 0, ok = 1;    int first = 1,kkk;    REP(i,0,7) {        if(ds[i]&1) od ++;        if(ds[i] != 0) {            if(first) {                kkk = Find(i);  first = 0;            }            else {                if(Find(i) != kkk) ok = 0;            }        }    }    if(ok == 0 || od!=0 && od!=2) printf("No solution\n");    else {        if(od == 0) dfs(r);        else {            int i;            for(i=0; i<=6; i++) if(ds[i]&1) break;            dfs(i);        }        for(int i=pa-1; i>=0; i--) {            int x = abs(ans[i]);            printf("%d %c\n", x, x == ans[i] ? '+' : '-');        }    }    return 0;}


原创粉丝点击