介紹的內容html
博客2ios
題意:spa
歐拉回路是指不令筆離開紙面,可畫過圖中每條邊僅一次,且能夠回到起點的一條迴路。現給定一個圖,問是否存在歐拉回路?.net
#include<iostream> #include<cstdio> #include <cctype> #include<algorithm> #include<cstring> #include<cmath> #include<string> #include<cmath> #include<set> #include<vector> #include<stack> #include<queue> #include<map> using namespace std; #define ll long long #define mem(a,x) memset(a,x,sizeof(a)) #define se second #define fi first const ll mod=998244353; const int INF= 0x3f3f3f3f; const int N=2e5+5; int n,m; int du[1005]; int f[1005]; int getf(int x) { if(x!=f[x]) { f[x]=getf(f[x]); } return f[x]; } int main() { int a,b,fa,fb; while(cin>>n && n) { cin>>m; int cnt=0; mem(f,0); mem(du,0); for(int i=0;i<=n;i++) f[i]=i; while(m--) { cin>>a>>b; du[a]++; du[b]++; fa=getf(a); fb=getf(b); if(fa!=fb) { f[fa]=fb; } else cnt++; //若是fa==fb,則兩個節點在同一並查集中, //這樣的狀況有且只能出現一次 ,不然走的路徑會存在重複 } if(cnt!=1) { cout<<0<<endl; continue; } int flag=0; for(int i=1;i<=n;i++) { if(du[i]%2!=0){ flag=1; break; } } cout<< (flag? 0:1)<<endl; } }
題目:Watchcowcode
題意:blog
求無向圖每條邊剛好通過兩次,在回到原點,輸出通過的頂點。容易轉化爲有向圖歐拉回路每條邊通過一次。ip
#include<iostream> #include<cstdio> #include <cctype> #include<algorithm> #include<cstring> #include<cmath> #include<string> #include<cmath> #include<set> #include<vector> #include<stack> #include<queue> #include<map> using namespace std; #define ll long long #define mem(a,x) memset(a,x,sizeof(a)) #define se second #define fi first const ll mod=998244353; const int INF= 0x3f3f3f3f; const int N=2e5+5; int n,m,cnt=0; int ans[200005]; struct edge { int to,flag; edge(int _to,int _flag):to(_to),flag(_flag){} }; vector<edge> v[200005]; void dfs(int x) { for(int i=0;i<v[x].size();i++) { if(v[x][i].flag==0) { v[x][i].flag=1; dfs(v[x][i].to); } } ans[++cnt]=x; } int main() { int a,b; cin>>n>>m; while(m--) { scanf("%d%d",&a,&b); v[a].push_back(edge(b,0)); v[b].push_back(edge(a,0)); } dfs(1); //printf("1\n"); for(int i=1;i<=cnt;i++) printf("%d\n",ans[i]); return 0; }
題意:
給你無向圖的N個點和M條邊,保證這M條邊都不一樣且不會存在同一點的自環邊,如今問你至少要幾筆才能全部邊都畫一遍.(一筆畫的時候筆不離開紙)
思路:
(1)若是該連通份量是一個孤立的點,即num[i]==0或num[i]==1的時候,注意num[i]==0表示i不是根節點,num[i]==1表示的是獨立的點。
(2)若是該連通份量是歐拉圖或半歐拉圖,那麼只須要1筆便可,即num[i]>1且sum[i]==0的時候,表示是(半)歐拉圖。
(3)若是該連通份量不是一個歐拉圖時,那麼咱們須要奇數度點個數/2,即num[i]>1且sum[i]>0時須要sum[i]/2筆。
#include<iostream> #include<cstdio> #include <cctype> #include<algorithm> #include<cstring> #include<cmath> #include<string> #include<cmath> #include<set> #include<vector> #include<stack> #include<queue> #include<map> using namespace std; #define ll long long #define mem(a,x) memset(a,x,sizeof(a)) #define se second #define fi first const ll mod=998244353; const int INF= 0x3f3f3f3f; const int N=2e5+5; int n,m; int du[N],f[N],num[N],sum[N]; //num[i]表示祖宗節點爲i的並查集內有多少個節點 //sum[i]表示祖宗節點爲i的並查集內 度數爲奇數的節點數量 int getf(int x) { if(x!=f[x]) { f[x]=getf(f[x]); } return f[x]; } int main() { int a,b,fa,fb,cnt; while(cin>>n>>m) { mem(f,0); mem(du,0); mem(num,0); mem(sum,0); int ans=0; for(int i=0;i<=n;i++) f[i]=i; for(int i=1;i<=m;i++) { cin>>a>>b; du[a]++; du[b]++; fa=getf(a); fb=getf(b); if(fa!=fb) f[fa]=fb; } for(int i=1;i<=n;i++) { num[getf(i)]++; if(du[i]&1) sum[getf(i)]++; } for(int i=1;i<=n;i++) { if(num[i]==0 || num[i]==1) continue; //表示節點i是孤立的 if(sum[i]>0) ans+=sum[i]/2; else if(sum[i]==0) ans++; } cout<<ans<<endl; } }