題意:
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") ;
}
}
}
}