1. 程式人生 > >HDU 1878 歐拉回路

HDU 1878 歐拉回路

題意:

歐拉回路的判斷條件,
一、無向圖
每個頂點的度數都是偶數,則存在歐拉回路。
二、有向圖(所有邊都是單向的)
每個節頂點的入度都等於出度,則存在歐拉回路。
以上兩種情況都很好理解。其原理就是每個頂點都要能進去多少次就能出來多少次。
三、混合圖(有的邊是單向的,有的邊是無向的。常被用於比喻城市裡的交通網路,有的路是單行道,有的路是雙行道。)
找到一個給每條無向的邊定向的策略,使得每個頂點的入度等於出度,這樣就能轉換成上面第二種情況。這就可以轉化成一個二部圖最大匹配問題。網路模型如下:

  1. 新建一個圖。
  2. 對於原圖中每一條無向邊i,在新圖中建一個頂點e(i);
  3. 對於原圖中每一個頂點j,在新圖中建一個頂點v(j)。
  4. 如果在原圖中,頂點j和k之間有一條無向邊i,那麼在新圖中從e(i)出發,新增兩條邊,分別連向v(j)和v(k),容量都是1。
  5. 在新圖中,從源點向所有e(i)都連一條容量為1的邊。
  6. 對於原圖中每一個頂點j,它原本都有一個入度in、出度out和無向度un。顯然我們的目的是要把所有無向度都變成入度或出度,從而使它的入度等於總度數的一半,也就是(in + out + un) / 2(顯然與此同時出度也是總度數的一半,如果總度數是偶數的話)。當然,如果in已經大於總度數的一半,或者總度數是奇數,那麼歐拉回路肯定不存大。如果in小於總度數的一半,並且總度數是偶數,那麼我們在新圖中從v(j)到匯點連一條邊,容量就是(in + out + un) / 2 – in,也就是原圖中頂點j還需要多少入度。
    按照這個網路模型算出一個最大流,如果每條從v(j)到匯點的邊都達到滿流量的話,那麼歐拉回路成立。

代價:

//
//  Created by  CQU_CST_WuErli
//  Copyright (c) 2016 CQU_CST_WuErli. All rights reserved.
//
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <cctype>
#include <cmath>
#include <string>
#include <vector>
#include <list>
#include <map> #include <queue> #include <stack> #include <set> #include <algorithm> #include <sstream> #define CLR(x) memset(x,0,sizeof(x)) #define OFF(x) memset(x,-1,sizeof(x)) #define MEM(x,a) memset((x),(a),sizeof(x)) #define BUG cout << "I am here" << endl #define lookln(x) cout << #x << "=" << x << endl #define SI(a) scanf("%d",&a) #define SII(a,b) scanf("%d%d",&a,&b) #define SIII(a,b,c) scanf("%d%d%d",&a,&b,&c) #define rep(flag,start,end) for(int flag=start;flag<=end;flag++) #define Rep(flag,start,end) for(int flag=start;flag>=end;flag--) #define Lson l,mid,rt<<1 #define Rson mid+1,r,rt<<1|1 #define Root 1,n,1 const int INF_INT=0x3f3f3f3f; const long long INF_LL=0x7fffffff; const int MOD=1e9+7; const double eps=1e-9; const double pi=acos(-1); typedef long long ll; using namespace std; const int N=1010; int n,m; vector<int> g[N]; int vis[N]; int deg[N]; void dfs(int u) { vis[u]=1; for (int i=0;i<g[u].size();i++){ int v=g[u][i]; if (vis[v]) continue; dfs(v); } } int main(int argc, char const *argv[]) { #ifdef LOCAL freopen("C:\\Users\\john\\Desktop\\in.txt","r",stdin); // freopen("C:\\Users\\john\\Desktop\\out.txt","w",stdout); #endif while(SII(n,m)==2 && n) { CLR(deg); rep(i,1,n) g[i].clear(); rep(i,1,m) { int u,v; SII(u,v); g[u].push_back(v); g[v].push_back(u); deg[u]++;deg[v]++; } int ans=1; CLR(vis); dfs(1); rep(i,1,n) if (!vis[i]) ans=0; int cnt=0; rep(i,1,n) if (deg[i]%2==1) cnt++; if (cnt) ans=0; cout << ans << endl; } return 0; }