HDU 6311 Cover 尤拉路徑,覆蓋
阿新 • • 發佈:2018-11-02
題意:n點m條邊的無向圖,問最少用多少條路徑覆蓋整張圖,要求任意兩個路徑都不能有公共邊. 並輸出這些路徑.n,m<=1e5.
假如原圖為尤拉圖,那麼顯然只需要用一條迴路.
一條路徑中,最多隻會包含兩個奇數點,那麼答案>=odd/2 (odd為奇數點的個數.)
現在可以構造該答案.將奇數點兩兩連上虛擬邊.總共odd/2條邊.
在新的圖上跑一次歐拉回路,回溯時不標記這些虛擬邊,則迴路被拆成若干條路徑.
注意多個連通分量,以及孤立點的情況.
#include <bits/stdc++.h> using namespace std; const int N=1e5+5; int n,m,num,tot,head[N],deg[N]; bool vis[N]; vector<int> ans[N]; struct node{ int v,id,nxt,flag; }e[N*4]; void add(int u,int v,int id){ e[tot].v=v,e[tot].id=id; e[tot].flag=0; e[tot].nxt=head[u],head[u]=tot++; } void dfs(int u){ vis[u]=1; for(int i=head[u];i!=-1;i=e[i].nxt){ int v=e[i].v; if(e[i].flag==false){ e[i].flag=e[i^1].flag=true; dfs(v); if(e[i].id) ans[num].push_back(-e[i].id); else num++; } } } int main(){ ios::sync_with_stdio(false);cin.tie(0); while(cin>>n>>m){ for(int i=0;i<=n;i++){ deg[i]=vis[i]=0; head[i]=-1; ans[i].clear(); } tot=num=0; for(int i=1;i<=m;i++){ int u,v; cin>>u>>v; deg[u]++,deg[v]++; add(u,v,i); add(v,u,-i); } int pre=0; for(int i=1;i<=n;i++){ if(deg[i]&1){ if(pre) add(i,pre,0),add(pre,i,0),pre=0; else pre=i; } } for(int i=1;i<=n;i++) if(!vis[i]&&(deg[i]&1)) num++,dfs(i),num--; for(int i=1;i<=n;i++) if(!vis[i]&°[i])//非孤立點 num++,dfs(i); cout<<num<<'\n'; for(int i=1;i<=num;i++){ cout<<ans[i].size(); for(int j=0;j<ans[i].size();j++) cout<<' '<<ans[i][j]; cout<<'\n'; } } return 0; }
求歐拉回路:dfs找到任意一個環 (dfs到一個點u:它沒有其他邊可以遍歷) 圖中剩下部分還是一條歐拉回路.從點u開始回溯,找剩下的環即可.