HDU 1878 歐拉回路
阿新 • • 發佈:2019-01-25
題意:
歐拉回路的判斷條件,
一、無向圖
每個頂點的度數都是偶數,則存在歐拉回路。
二、有向圖(所有邊都是單向的)
每個節頂點的入度都等於出度,則存在歐拉回路。
以上兩種情況都很好理解。其原理就是每個頂點都要能進去多少次就能出來多少次。
三、混合圖(有的邊是單向的,有的邊是無向的。常被用於比喻城市裡的交通網路,有的路是單行道,有的路是雙行道。)
找到一個給每條無向的邊定向的策略,使得每個頂點的入度等於出度,這樣就能轉換成上面第二種情況。這就可以轉化成一個二部圖最大匹配問題。網路模型如下:
- 新建一個圖。
- 對於原圖中每一條無向邊i,在新圖中建一個頂點e(i);
- 對於原圖中每一個頂點j,在新圖中建一個頂點v(j)。
- 如果在原圖中,頂點j和k之間有一條無向邊i,那麼在新圖中從e(i)出發,新增兩條邊,分別連向v(j)和v(k),容量都是1。
- 在新圖中,從源點向所有e(i)都連一條容量為1的邊。
- 對於原圖中每一個頂點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;
}