今天继续划水,来讲一讲欧拉路问题。
欧拉路,简单来说就是一笔画,即对于一张图,可以从某个点出发,经过每一条边,遍历完整张图,这个路径就称为欧拉路径。如果起点与终点重合,则称为欧拉回路。那么,应该如何判断欧拉路呢?
我们先定义几个概念,在无向图中,我们称有奇数条连接的边的点为奇点,有偶数条连接的边的点为偶点。对于有向图,我们设度数为出度减入度的值。
首先,应该判断连通性(dfs),如果这一个图不连通,则一定不是欧拉路。之后从其是否有向进行判断。
1.对于无向连通图,若节点全部为偶点,那么是欧拉回路,若只有两个奇点,其余全部为偶点,那么是欧拉路。
2.对于有向连通图,若所有的节点度数都为0,那么是欧拉回路,若起点度数为1,终点度数为-1,其余节点度数全部为0,那么是欧拉路。
例题1 hdu1878
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 23884 Accepted Submission(s): 9310
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int maxn=1005; 4 using ll = long long; 5 int du[maxn]; 6 bool vis[maxn]; 7 vector<int> g[maxn]; 8 void dfs(int x){ 9 vis[x]=1; 10 for(int i=0;i<g[x].size();i++){ 11 if(!vis[g[x][i]])dfs(g[x][i]); 12 } 13 } 14 int main() { 15 ios::sync_with_stdio(false); 16 cin.tie(0); 17 cout.tie(0); 18 int n,m; 19 while(1){ 20 cin>>n; 21 if(n==0)break; 22 cin>>m; 23 memset(du,0,sizeof(du)); 24 for(int i=1;i<=n;i++)g[i].clear(); 25 memset(vis,0,sizeof(vis)); 26 while(m--){ 27 int x,y; 28 cin>>x>>y; 29 g[x].push_back(y); 30 g[y].push_back(x); 31 du[x]++; 32 du[y]++; 33 } 34 int flag=1; 35 for(int i=1;i<=n;i++){ 36 if(du[i]&1){ 37 flag=0; 38 break; 39 } 40 } 41 dfs(1); 42 for(int i=1;i<=n;i++){ 43 if(!vis[i]){ 44 flag=0; 45 break; 46 } 47 } 48 cout<<flag<<endl; 49 } 50 return 0; 51 }
例题2 hdu1116
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 12319 Accepted Submission(s): 4314
1 #include <bits/stdc++.h> 2 using namespace std; 3 using ll = long long; 4 const int maxn=30; 5 vector<int>g[maxn]; 6 bool vis[maxn]; 7 bool exi[maxn]; 8 int du[maxn]={0}; 9 void dfs(int x){ 10 vis[x]=1; 11 for(int i=0;i<(int)g[x].size();i++){ 12 int nex=g[x][i]; 13 if(!vis[nex])dfs(nex); 14 } 15 } 16 int main() { 17 ios::sync_with_stdio(false); 18 cin.tie(0); 19 cout.tie(0); 20 int t; 21 cin>>t; 22 while(t--){ 23 int m; 24 cin>>m; 25 int flag=1; 26 memset(exi,0,sizeof(exi)); 27 memset(du,0,sizeof(du)); 28 memset(exi,0,sizeof(exi)); 29 memset(vis,0,sizeof(vis)); 30 for(int i=0;i<maxn;i++)g[i].clear(); 31 while(m--){ 32 string s; 33 cin>>s; 34 int x=s[0]-‘a‘,y=s[s.size()-1]-‘a‘; 35 g[x].push_back(y); 36 du[x]++; 37 du[y]--; 38 exi[x]=1; 39 exi[y]=1; 40 } 41 int cnt1=0; 42 int cnt2=0; 43 int cnt3=0; 44 int start=0; 45 for(int i=0;i<=25;i++){ 46 if(du[i]==1){ 47 cnt1++; 48 start=i; 49 } 50 if(du[i]==-1)cnt2++; 51 if(du[i]!=1&&du[i]!=0&&du[i]!=-1)cnt3++; 52 } 53 if((cnt1==1&&cnt2==1) || (cnt1==0&&cnt2==0))flag=1; 54 else flag=0; 55 if(cnt1&&cnt2&&(cnt1+cnt2>2))flag=0; 56 if(cnt3>0)flag=0; 57 dfs(start); 58 for(int i=0;i<=25;i++){ 59 if(exi[i]&&(!vis[i]))flag=0; 60 } 61 if(flag)cout<<"Ordering is possible."<<endl; 62 else cout<<"The door cannot be opened."<<endl; 63 } 64 return 0; 65 }
例题3 hdu5883
Time Limit: 9000/3000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others)
Total Submission(s): 3419 Accepted Submission(s): 1388
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int maxn=(1e5)+5; 5 const int maxm=(5e5)+5; 6 ll a[maxn]; 7 ll du[maxn]; 8 int main(){ 9 int t; 10 cin>>t; 11 while(t--){ 12 int n,m; 13 memset(du,0,sizeof(du)); 14 scanf("%d%d",&n,&m); 15 for(int i=1;i<=n;i++)scanf("%lld",&a[i]); 16 for(int i=1;i<=m;i++){ 17 ll x,y; 18 scanf("%lld%lld",&x,&y); 19 du[x]++; 20 du[y]++; 21 } 22 int cnt=0; 23 int start; 24 for(int i=1;i<=n;i++){ 25 if(du[i]&1){ 26 cnt++; 27 start=i; 28 } 29 } 30 bool flag=1; 31 ll ans=0; 32 if(cnt==2){ //欧拉通路 33 for(int i=1;i<=n;i++){ 34 for(int j=1;j<=du[i]/2;j++){ 35 ans^=a[i]; 36 } 37 if(du[i]&1)ans^=a[i]; 38 } 39 } 40 else if(cnt==0){ //欧拉回路 41 for(int i=1;i<=n;i++){ 42 for(int j=1;j<=du[i]/2;j++){ 43 ans^=a[i]; 44 } 45 } 46 int ans0=ans; 47 for(int i=1;i<=n;i++){ 48 ans=max(ans0,ans0^a[i]); 49 } 50 } 51 else flag=0; 52 if(flag)printf("%lld\n",ans); 53 else printf("Impossible\n"); 54 } 55 return 0; 56 }
原文:https://www.cnblogs.com/yokino/p/15175360.html