欧拉回路
题目:给你一串字符串,问你是否能够将字符串相连,是他们的首位字母想同,如asdjlj,jadlsajdl,ldaskdak就行
解法:明显的欧拉回路问题,要有欧拉回路对于无向图首先要每个顶点的度为偶数或者有两个奇度顶点,其余均为偶度顶点,其次,整个图要输一个连通图
对于有向图,一个点出度比入度大1(起点),一个点入度比出度大1(终点)
输入:输入n,表示字符串个数,接下来n行分别表示n个字符串
输出:输出首尾相连排序后的字符串
代码
#include<iostream> #include<stack> #include<string> #include<cmath> #include<stack> using namespace std; string strs[27][27][10]; int map[27][27]; int vis[27][27]; int in[27]; int out[27]; int father[27]; int start; stack<string> st; int find(int n) { while(n!=father[n]) n=father[n]; return n; } void merge(int a,int b) { a=find(a); b=find(b); if(a!=b) father[b]=a; } bool judge()//判断出入度 { int cnt1=0; int cnt_1=0; for(int i=1;i<27;++i) { if(abs(cnt1-cnt_1)>1) return false; if(in[i]-out[i]==1) cnt1++; if(out[i]-in[i]==1) { start=i; cnt_1++; } } if(cnt1==1&&cnt_1==1) return true; return false; } void oular(int n) { for(int i=1;i<27;++i) { if(map[n][i]&&(vis[n][i]<map[n][i])) { int temp=++vis[n][i]; oular(i); st.push(strs[n][i][vis[n][i]]); } } } int main() { int n; cin>>n; string str; for(int i=0;i<27;++i) father[i]=i; while(n--) { cin>>str; int a=str[0]-'a'+1; int b=str[str.length()-1]-'a'+1; out[a]++; in[b]++; merge(a,b);//并查集 strs[a][b][++map[a][b]]=str; } bool flag=true; int cnt=0; for(int i=1;i<27;++i) { if((in[i]||out[i])&&father[i]==i) cnt++; } if(cnt!=1) flag=false; if(!judge()) flag=false; if(flag==false) cout<<"无法开门"<<endl; else { oular(start); } while(!st.empty()) { cout<<st.top()<<endl; st.pop(); } return 0; }
拓扑排序
dfs版本
代码
//拓扑排序 #include<iostream> #include<cstring> #include<time.h> using namespace std; #define maxn 100 int graph[100][100]; //a与b之间有边 int c; int via[maxn]; int topo[maxn]; int n; bool dfs(int x) { via[x]=-1; for(int i=1;i<=n;++i) { if(graph[x][i]) { if(via[i]==-1) return false; else { if(!via[i]&&!dfs(i)) return false;//有返回值时,每布都要判断一下 } } } via[x]=1; topo[--c]=x; return true; } bool toposort() { c=n; memset(via,0,sizeof(via)); for(int i=1;i<=n;++i) { if(!via[i]) { if(!dfs(i)) return false; } } return true; } int main() { memset(graph,0,sizeof(graph)); memset(topo,0,sizeof(topo)); cout<<"输入点的个数"<<endl; cin>>n; int m; cout<<"输入边的条数"<<endl; cin>>m; int a,b; while(m--) { cin>>a>>b; graph[a][b]=1; } clock_t start=clock(); bool flag=toposort(); if(flag) { for(int i=0;i<n;++i) cout<<topo[i]<<" "; cout<<endl; } else cout<<"该图有圈"<<endl; clock_t end=clock(); cout<<(double)(end-start)/CLOCKS_PER_SEC*1000<<endl; return 0; }
bfs版本
#include<iostream> #include<queue> using namespace std; int in[100]; int out[100]; int map[100][100]; int topo[100]; int c=0; int n,m; void bfs(int x) { queue<int> q; int n1,n2; n1=x; q.push(n1); while(!q.empty()) { n1=q.front(); q.pop(); topo[++c]=n1; for(int i=1;i<=n;++i) { if(map[n1][i]!=0) { in[i]--; if(in[i]==0) q.push(i); } } } } int main() { cout<<"请输入顶点个数"<<endl; cin>>n; cout<<"请输入边的个数"<<endl; cin>>m; cout<<"请输入各边"<<endl; for(int i=1;i<=m;++i) { int a,b; cin>>a>>b; map[a][b]=1; in[b]++; out[a]++; } bfs(1); cout<<"答案为"<<endl; if(c<n) cout<<"该图有圈"<<endl; else for(int i=1;i<=c;++i) cout<<topo[i]<<endl; return 0; }
最短路径bfs求法
代码
#include<iostream> #include<queue> #include<cstring> #include<vector> #include<algorithm> using namespace std; int map[100][100]; int d[100]; int flag[100]; int n,m; void bfs(int x) { int n1,n2; queue<int> q; n1=x; q.push(n1); while(!q.empty()) { n1=q.front(); q.pop(); for(int i=1;i<=n;++i) { if(d[i]>(d[n1]+map[n1][i])) { d[i]=d[n1]+map[n1][i]; q.push(i); } } } } int main() { memset(map,0x3f,sizeof(map)); memset(d,0x3f,sizeof(d)); cout<<"请输入顶点个数"<<endl; cin>>n; for(int i=1;i<=n;++i) map[i][i]=0; cout<<"请输入边的个数"<<endl; cin>>m; cout<<"请输入边和权值"<<endl; for(int i=1;i<=m;++i) { int a,b,c; cin>>a>>b>>c; map[a][b]=c; } d[1]=0; bfs(1); cout<<"答案为"<<endl; for(int i=1;i<=n;++i) cout<<d[i]<<endl; return 0; }