心得:Topsort不仅用于job/work的排序,字典序的排序,还可以适用于任意具有偏序关系的问题,
只要可以把问题转换为有向无环图,然后知晓其偏序,之后就是表示边/入度,然后用拓扑排序的思想去计算。
注意拓扑排序的唯一性是在全序关系的条件下建立起来的
注意拓扑排序是针对有向五环图。
欧拉回路和哈密顿路径:
哈密顿路径:经过所有的顶点正好访问一次的路径。
Knhn算法的实现:考虑入度为0的点
DFS算法的实现:考虑出度为0的点
uva,200
一开始没看懂,后来知道了,是给你几行索引是按照一种语言的字典序排序的
例如: xwy zx z>x zxy zxw w>y zxw ywwx y>z 最后字母的大小顺序 x<z<y<w
1 #include <iostream> 2 #include <cstdio> 3 #include <string> 4 #include <vector> 5 using namespace std; 6 7 vector<char> ans; 8 vector<char> toPoint[100]; 9 int visit[100] = {0}; 10 int deg[100] = {0}; // deg[i]=1:沒有被其他點連入 deg[i]=2:被其他點連入 11 void DFS(char n); 12 13 int main() 14 { 15 // freopen("input.txt","rt",stdin); 16 ios::sync_with_stdio(false); 17 string a, b; 18 cin >> a; 19 while (cin >> b && b != "#") { 20 int L = (a.size() > b.size()) ? b.size() : a.size(); 21 for (int i = 0; i < L; ++i) { 22 if (deg[a[i]] == 0) deg[a[i]] = 1; 23 if (deg[b[i]] == 0) deg[b[i]] = 1; 24 if (b[i] != a[i]) { 25 toPoint[a[i]].push_back(b[i]); 26 deg[b[i]] = 2; 27 break; 28 } 29 } 30 a = b; 31 } 32 for (char i = 'A'; i <= 'Z'; ++i) 33 if (deg[i] == 1) 34 DFS(i); 35 36 for (auto iter = ans.rbegin(); iter != ans.rend(); ++iter) 37 cout << *iter; 38 cout << endl; 39 } 40 void DFS(char n) 41 { 42 if (visit[n] == 1) return; 43 visit[n] = 1; 44 45 for (char nxt : toPoint[n]) 46 if (visit[nxt] != 2) 47 DFS(nxt); 48 visit[n] = 2; 49 ans.push_back(n); 50 }
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 5 using namespace std; 6 7 char list[10001][100]; 8 int map[27][27]; 9 int used[27]; 10 int stack[27]; 11 int stack_size=0; 12 13 void dfs(int s) 14 { 15 used[s]=0; 16 for(int i=0;i<27;++i) 17 if(used[i] && map[s][i]) 18 dfs(i); 19 stack[stack_size++]=s+'A'; 20 } 21 22 int main() 23 { 24 int count=0; 25 while(scanf("%s",list[count]) && list[count][0]!='#') 26 count++; 27 memset(used,0,sizeof(used)); 28 memset(map,0,sizeof(map)); 29 used[list[0][0]-'A']=1; 30 31 for(int i=1;i<count;i++) 32 { 33 for(int p=0,q=0;list[i-1][p] && list[i][q];++p,++q) 34 { 35 36 used[list[i-1][p]-'A']=used[list[i][q]-'A']=1; 37 if(list[i-1][p]!=list[i][q]) 38 { 39 map[list[i-1][p]-'A'][list[i][q]-'A']=1; 40 used[list[i][q]-'A']=2; 41 break; 42 } 43 } 44 } 45 46 for(int i=0;i<27;i++) 47 if(used[i]==1) 48 dfs(i); 49 while(stack_size--) 50 printf("%c",stack[stack_size]); 51 printf(" "); 52 return 0; 53 54 }
uva,10305
dfs搞一搞就可以了
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 5 using namespace std; 6 const int maxn=105; 7 8 int map[maxn][maxn]; 9 int visit[maxn]; 10 int stack[maxn]; 11 int stack_size; 12 int n,m; 13 14 void dfs(int s) 15 { 16 visit[s]=1; 17 for(int i=1;i<=n;i++) 18 if(map[s][i] && !visit[i]) 19 dfs(i); 20 stack[--stack_size]=s; 21 } 22 23 int main() 24 { 25 while(scanf("%d%d",&n,&m) && m+n) 26 { 27 memset(map,0,sizeof(map)); 28 int a,b; 29 for(int i=0;i<m;i++) 30 { 31 scanf("%d%d",&a,&b); 32 map[a][b]=1; 33 } 34 stack_size=n; 35 memset(visit,0,sizeof(visit)); 36 for(int i=1;i<=n;i++) 37 if(!visit[i]) 38 dfs(i); 39 int i; 40 for(i=0;i<n-1;i++) 41 printf("%d ",stack[i]); 42 printf("%d ",stack[i]); 43 } 44 return 0; 45 }
uva,124
参考了大神的代码,第一次接触拓扑排序,我还只停留在一维的思想上,只会打印一组拓扑排序结果,
用dfs把每种可能的结果都搜一下,然后加上限制条件,如果满足len=n则输出。。。。。真的妙!!!豁然开朗
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <string> 5 #include <algorithm> 6 #include <cstdlib> 7 8 using namespace std; 9 const int maxn=200; 10 11 char ch1[maxn],ch2[maxn],ch3[maxn]; 12 int n,m,a[maxn],edge[maxn][maxn],to[maxn],vis[maxn],zm[maxn]; 13 14 bool cmp(char a,char b) 15 { 16 return a<b; 17 } 18 19 void dfs(int len) 20 { 21 if(n==len) //当深度为n,也就是把每个点都访问一次 22 { 23 for(int i=0;i<n;i++) 24 printf("%c",ch3[a[i]]); //打印 25 printf(" "); 26 return; 27 } 28 29 for(int i=0;i<n;i++) 30 { 31 if(!vis[i] && !to[i]) 32 { 33 for(int j=0;j<n;j++) 34 if(edge[i][j]==1) //删边 35 to[j]--; 36 vis[i]=1; 37 a[len]=i; 38 dfs(len+1); 39 40 for(int j=0;j<n;j++) 41 if(edge[i][j]==1) //恢复现场,为下一个序列做准备 42 to[j]++; 43 vis[i]=0; 44 } 45 } 46 return; 47 } 48 49 int main() 50 { 51 int pd=0; 52 while(gets(ch1)) 53 { 54 int i; 55 if(!pd) 56 pd=1; 57 else 58 printf(" "); 59 60 61 for(i=0,n=0;ch1[i];i++) 62 { 63 if(ch1[i]==' ') 64 continue; 65 ch3[n++]=ch1[i]; //筛选 66 } 67 68 sort(ch3,ch3+n,cmp); //按字典序 69 70 memset(zm,-1,sizeof(zm)); 71 memset(edge,-1,sizeof(edge)); 72 memset(to,0,sizeof(to)); 73 memset(vis,0,sizeof(vis)); 74 75 for(int i=0;i<n;i++) 76 { 77 zm[ch3[i]-'a']=i; //剪枝,大大降低整体复杂度 78 } 79 80 gets(ch2); 81 82 for(i=0;ch2[i];i+=4) 83 { 84 edge[zm[ch2[i]-'a']][zm[ch2[i+2]-'a']]=1; //建边 85 to[zm[ch2[i+2]-'a']]++; //入度增1 86 } 87 dfs(0); 88 } 89 return 0; 90 }
对next_permutation函数求出所以的排列,然后限制条件,最后输出。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <string> 5 #include <cstdlib> 6 #include <algorithm> 7 8 using namespace std; 9 const int maxn=200; 10 11 char ch1[maxn],ch2[maxn],ch3[maxn]; 12 int n,edge[maxn][maxn],to[maxn],vis[maxn],a[maxn],zm[maxn]; 13 14 15 bool cmp(char a,char b) 16 { 17 return a<b; 18 } 19 20 int Topsort(char ch[]) 21 { 22 for(int i=n-1;i>0;i--) 23 for(int j=i-1;j>=0;j--) 24 if(edge[zm[ch[i]-'a']][zm[ch[j]-'a']]==1) 25 return 0; 26 return 1; 27 } 28 29 int main() 30 { 31 int i,pd=0; 32 while(gets(ch1)) 33 { 34 if(!pd) 35 pd=1; 36 else 37 printf(" "); 38 gets(ch2); 39 for(i=0,n=0;ch1[i];i++) 40 { 41 if(ch1[i]==' ') 42 continue; 43 ch3[n++]=ch1[i]; 44 } 45 ch3[n]='