0w1

UVA 10054 The Necklace ( Euler's Path )

UVa Online Judge
可以把顏色當作節點,則珠子就是節點之間的邊,題目要求就等價於問是否能用每個邊恰好一次構成一個迴路。這就是經典的尤拉迴路問題。
若滿足"所有點構成的圖聯通且不存在奇度數的節點"則必有尤拉迴路( 而且隨便走都是 ),而尤拉路徑除此之外還允許兩個奇點存在( 一頭一尾 )。
這題要特別注意的是存在重邊,所以要用++ / -- 處理邊數,還有輸出時要逆序( 後序 ),因為會有迴朔的問題,可以想像是一個節點多方向延伸,所以不能前序輸出。

#include <bits/stdc++.h>
using namespace std;
const int MAXN = 50 + 5;

int kase;
int n;
int vis[MAXN], deg[MAXN], G[MAXN][MAXN];

bool hasOdd(){
    for(int i = 1; i <= 50; ++i)
        if( deg[i] & 1 )
            return true;
    return false;
}

void euler(int u){
    for(int v = 1; v <= 50; ++v)
        if( G[u][v] ){ // 隨便走都對,把無向邊刪去再繼續
            --G[u][v], --G[v][u];
            euler( v );
            printf("%d %d\n", v, u);
        }
}

void solve(){
    if( hasOdd() ){
        puts("some beads may be lost");
        return;
    }
    for(int i = 1; i <= 50; ++i)
        if( deg[i] ){
            euler( i );
            break;
        }
}

void init(){
    memset( G, 0, sizeof(G) );
    memset( deg, 0, sizeof(deg) );
}

int main(){
    int T; scanf("%d", &T);
    while( T-- ){
        printf("Case #%d\n", ++kase);
        scanf("%d", &n);
        init();
        for(int i = 0; i < n; ++i){
            int a, b; scanf("%d %d", &a, &b);
            ++G[a][b], ++G[b][a], ++deg[a], ++deg[b];
        }
        solve();
        if( T ) puts("");
    }
    return 0;
}