SGU 001

題意:

N個多米諾骨牌,每個骨牌左右兩側分別有一個0~6的整數(骨牌可以旋轉以調換其左右兩數),求一種把這些骨牌從左到右排列的方案,使得所有相鄰的兩數字相等(即左邊骨牌右側的數字等於右邊骨牌左側的數字)。

解法:

求歐拉路徑,注意判斷歐拉路徑存不存在.

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

const int N = 1e2+11 ;

struct Edge {
    int next, to ;
    Edge(){}
    Edge(int a , int b):next(a) , to(b){}
};

int head[N] ; Edge err[N*10] ; int nedge ;
bool vis[N*10] ;
int degree[10] ; int fa[10] ;
int site[N][2] ;
int ans[N][3] ;
vector<int> stk ;
int n ;

void add_edge(int a , int b) {
    err[++nedge] = Edge(head[a] , b) ;
    vis[nedge] = false ;
    head[a] = nedge ;
    err[++nedge] = Edge(head[b] , a) ;
    vis[nedge] = false ;
    head[b] = nedge ;
}

int find(int x) {
    if(fa[x] != x) fa[x] = find(fa[x]) ;
    return fa[x] ;
}

void dfs(int u) {
    for(int i = head[u] ; i != -1 ; i = err[i].next) {
        int v = err[i].to ;
        if(vis[i] == false) {
            vis[i] = vis[i^1] = true ;
            dfs(v) ;
        }
    }
    stk.push_back(u) ;
}

int main() {
    //freopen("data.in" ,"r", stdin) ;
    while(scanf("%d" , &n)==1) {
        memset(head , -1 , sizeof(head)) ; nedge = -1 ;
        memset(degree , 0 , sizeof(degree)) ;
        for(int i = 0 ; i <= 6 ; ++i) fa[i] = i ;
        int a , b ;
        int s1 = 0 , s2 = 0 ;
        for(int i = 1 ; i <= n ; ++i) {
            scanf("%d %d" , &a ,&b) ;
            site[i][0] = a , site[i][1] = b ;
            add_edge(i , n+a+1) ;
            add_edge(i , n+b+1) ;
            //注意a和b相等的時候
            if(degree[a] == 0) ++s1 ;
            ++degree[a] ;
            if(degree[b] == 0) ++s1 ;
            ++degree[b] ;
            int a1 = find(a) ;
            int b1 = find(b) ;
            if(a1 != b1) ++s2 , fa[a1] = b1 ;
        }
        if(s2+1 != s1) {
            printf("No solution\n") ;
            continue ;
        }
        int ss = 0 , start = 0 ;
        for(int i = 0 ; i <= 6 ; ++i) if(degree[i]%2) ++ss , start = i ;
        if(start == 0 && degree[0] == 0) for(int i = 1 ; i <= 6 ; ++i) if(degree[i] > 0) start = i ;
        if(!(ss == 2 || ss == 0)) {
            printf("No solution\n") ;
            continue ;
        }
        stk.clear() ;
        dfs(start+n+1) ;
        ss = 0 ;
        for(int i = 1 ; i < stk.size() ; i += 2) {
            int lef = stk[i-1]-n-1 , rig = stk[i+1]-n-1 ;
            ++ss ;
            ans[ss][0] = lef , ans[ss][1] = rig , ans[ss][2] = stk[i] ;
        }
        for(int i = 1 ; i <= n ; ++i) {
            printf("%d ", ans[i][2]) ;
            int x = ans[i][2] ;
            if(ans[i][0] == site[x][0] && ans[i][1] == site[x][1]) {
                printf("+\n") ;
            }else {
                printf("-\n") ;
            }
        }
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章