【歐拉回路+DFS】GYM - 229073 - C. Promenade by the lake
阿新 • • 發佈:2018-11-10
題目連結<http://codeforces.com/gym/229073/problem/C>
題意:
有一張無向連通圖,新增若干條邊使圖存在歐拉回路。輸出任意一種方案。
題解:
- 無向圖存在歐拉回路的判斷條件是所有點的度數為偶數。
- 所以最後的添邊方案應該滿足:度為奇數的連奇數條邊,度為偶數的連偶數條邊。
- 考慮新加的一條鏈如:1—2—3—4—5,那麼鏈的兩端度數加1,鏈的中間度數加2。所以可以考慮構造從奇數點出發並且以奇數點結束的鏈。而如果有一些邊被重複利用如:1—2—3—4,5—2—3—6,也可以把這兩條鏈變成:1—2—5,4—3—6。
- 對於一個連通塊,如果奇數點的個數為奇數個,那麼不可能構造出來,直接輸出NO即可。
- 至於構造的方法可以用dfs建樹搜尋:搜尋每一個點下的子樹,如果子樹的度數為奇數,那麼就連一條邊。
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int N=5e5+7; struct Edge{ int u,v,nxt; Edge(int u=0,int v=0,int nxt=0):u(u),v(v),nxt(nxt){} }e[N*2]; bool tr[N*2]; int p[N],edn; void add(int u,int v){ e[++edn]=Edge(u,v,p[u]);p[u]=edn; e[++edn]=Edge(v,u,p[v]);p[v]=edn; } int n,m,k,u,v; int d[N],ds[N],dt[N],vis[N]; int f[N]; int fd(int x){return x==f[x]?x:f[x]=fd(f[x]);} void un(int x,int y){ int fx=fd(x),fy=fd(y); if(fx==fy) return; f[fx]=fy; ds[fy]+=ds[fx]; } vector<int>ans; void dfs(int u){ dt[u]=d[u]; vis[u]=1; for(int i=p[u];~i;i=e[i].nxt){ int v=e[i].v; if(vis[v]) continue; dfs(v); if(dt[v]&1){ dt[u]+=dt[v]; ans.push_back(i/2*2); } } } int main() { scanf("%d%d%d",&n,&m,&k); for(int i=1;i<=m;i++){ scanf("%d%d",&u,&v); d[u]=d[u]^1,d[v]=d[v]^1; } for(int i=1;i<=n;i++) f[i]=i,ds[i]=d[i]; memset(p,-1,sizeof(p));edn=-1; for(int i=1;i<=k;i++){ scanf("%d%d",&u,&v); un(u,v); add(u,v); } for(int i=1;i<=n;i++){ if(fd(i)!=i) continue; if(ds[i]&1){ printf("NO\n"); return 0; } dfs(i); } int sz=ans.size(); printf("YES\n%d\n",sz); for(int i=0;i<sz;i++) printf("%d %d\n",e[ans[i]].u,e[ans[i]].v); }