今天继续划水,来讲一讲欧拉路问题。
欧拉路,简单来说就是一笔画,即对于一张图,可以从某个点出发,经过每一条边,遍历完整张图,这个路径就称为欧拉路径。如果起点与终点重合,则称为欧拉回路。那么,应该如何判断欧拉路呢?
我们先定义几个概念,在无向图中,我们称有奇数条连接的边的点为奇点,有偶数条连接的边的点为偶点。对于有向图,我们设度数为出度减入度的值。
首先,应该判断连通性(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
Play on Words
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 12319 Accepted Submission(s): 4314
There is a large number of magnetic plates on every door. Every plate has one word written on it. The plates must be arranged into a sequence in such a way that every word begins with the same letter as the previous word ends. For example, the word ``acm‘‘ can be followed by the word ``motorola‘‘. Your task is to write a computer program that will read the list of words and determine whether it is possible to arrange all of the plates in a sequence (according to the given rule) and consequently to open the door.
If there exists such an ordering of plates, your program should print the sentence "Ordering is possible.". Otherwise, output the sentence "The door cannot be opened.".
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
The Best Path
Time Limit: 9000/3000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others)
Total Submission(s): 3419 Accepted Submission(s): 1388
For each test case, in the first line there are two positive integers N (N≤100000) and M (M≤500000), as described above. The i-th line of the next N lines contains an integer ai(?i,0≤ai≤10000) representing the number of the i-th lake.
The i-th line of the next M lines contains two integers ui and vi representing the i-th river between the ui-th lake and vi-th lake. It is possible that ui=vi.
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 }