拓扑排序
心得: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("\n"); 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\n",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("\n"); 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("\n"); 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("\n"); 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]='\0'; 46 sort(ch3,ch3+n,cmp); 47 memset(edge,-1,sizeof(edge)); 48 memset(vis,0,sizeof(vis)); 49 memset(to,0,sizeof(to)); 50 memset(zm,-1,sizeof(zm)); 51 52 53 for(i=0;i<n;i++) 54 { 55 zm[ch3[i]-'a']=i; 56 } 57 58 for(i=0;ch2[i];i+=4) 59 { 60 edge[zm[ch2[i]-'a']][zm[ch2[i+2]-'a']]=1; 61 to[zm[ch2[i+2]-'a']]++; 62 } 63 64 if(Topsort(ch3)) 65 printf("%s\n",ch3); 66 while(next_permutation(ch3,ch3+n)) 67 { 68 if(Topsort(ch3)) 69 printf("%s\n",ch3); 70 } 71 } 72 return 0; 73 }
uva,196
1 #include<cstdio> 2 #include<cstring> 3 #include<string> 4 #include<algorithm> 5 #include<queue> 6 #include<vector> 7 #include<iostream> 8 #include<cmath> 9 using namespace std; 10 const int maxn=2000005; // 开到百万即可 11 int row,col; // 行,列 12 int val[maxn]; // 数值 13 int GetId(int x,int y){ return (x-1)*col+y; } // 得到某个位置的id 14 string S[maxn]; 15 vector<int> G[maxn]; // 用动态数组建立临接表,我比较喜欢用这种方式 16 int indeg[maxn]; // 入度 17 int Get(const string& str) // 如果格子中是数值,则调用这个函数 18 { 19 int ret=0; 20 for(int i=0;i<str.size();i++) ret=ret*10+str[i]-'0'; 21 return ret; 22 } 23 void change_to_num(const string& str,int id) 24 { 25 int i; 26 for(i=0;i<str.size();i++) 27 { 28 if(str[i]>='0'&&str[i]<='9') break; // 找到字母和数字的分界位置 29 } 30 int R=0,C=0; 31 for(int j=0;j<i;j++) C=C*26+str[j]-'A'+1; // 分别计算行跟列 32 for(int j=i;j<str.size();j++) R=R*10+str[j]-'0'; 33 int to=GetId(R,C); 34 G[to].push_back(id); // 建表 35 indeg[id]++; 36 } 37 void link(const string& str,int id) 38 { 39 int pre=1; 40 int i; 41 for(i=1;i<str.size();i++) 42 { 43 if(str[i]=='+') 44 { 45 change_to_num(str.substr(pre,i-pre),id); //单独分离出来如=A1+B1+C1,分离出A1,B1, 46 pre=i+1; 47 } 48 } 49 change_to_num(str.substr(pre,i-pre),id); // 最后一个还要处理,如分离出最后的C1 50 } 51 void Get_Val(const string& str,int id) 52 { 53 if(str[0]!='=') val[id]=Get(str); // 如果是数值 54 else link(str,id); // 要建立临接表 55 } 56 queue<int> que; 57 void toposort() 58 { 59 while(!que.empty()) que.pop(); 60 for(int i=1;i<=row*col;i++) if(!indeg[i]) que.push(i); //入度为0 的加入队列 61 while(!que.empty()) 62 { 63 int now=que.front(); que.pop(); 64 for(int i=0;i<G[now].size();i++) 65 { 66 int to=G[now][i]; 67 indeg[to]--; 68 val[to]+=val[now]; //加上数值 69 if(!indeg[to]) que.push(to); //变为0就加入队列 70 } 71 } 72 } 73 void ans_print() 74 { 75 for(int i=1;i<=row;i++) 76 { 77 for(int j=1;j<=col;j++) 78 { 79 if(j!=1) printf(" "); 80 printf("%d",val[GetId(i,j)]); 81 } 82 printf("\n"); 83 } 84 } 85 int main() 86 { 87 int T; 88 scanf("%d",&T); 89 while(T--) 90 { 91 scanf("%d%d",&col,&row); 92 memset(val,0,sizeof(val)); 93 for(int i=1;i<=row*col;i++) G[i].clear(); 94 memset(indeg,0,sizeof(indeg)); 95 for(int i=1;i<=row;i++) 96 { 97 for(int j=1;j<=col;j++) 98 { 99 int id=GetId(i,j); // 得到他的id 100 cin>>S[id]; 101 Get_Val(S[id],id); // 处理 102 } 103 } 104 toposort(); // 拓扑排序 105 ans_print(); // 打印 106 } 107 return 0; 108 }
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <string> 5 #include <cmath> 6 #include <algorithm> 7 #include <cstdlib> 8 #define maxn 1010 9 #define MARK -2147483645 10 11 using namespace std; 12 13 int row,col; 14 int sheet[maxn][maxn]; 15 string str; 16 string formula[maxn][maxn]; 17 18 19 int dfs(int r,int c) 20 { 21 if(sheet[r][c]!=MARK) return sheet[r][c]; 22 if(sheet[r][c]==MARK) 23 { 24 int m_col,m_row; 25 26 string str=formula[r][c]; 27 sheet[r][c]=0; 28 char temp[maxn]; 29 30 for(int i=1,pos=0;i<=str.size()+1;i++) 31 { 32 int k; 33 if(str[i]=='+' || i==str.size()) 34 { 35 m_col=0;m_row=0; 36 temp[pos]='\0'; 37 for(k=0; k<strlen(temp) && !isdigit(temp[k]);++k) 38 m_col=m_col*26+temp[k]-'A'+1; 39 for(;k<strlen(temp);++k) 40 m_row=m_row*10+temp[k]-'0'; 41 42 pos=0; 43 sheet[r][c]+=dfs(m_row,m_col); 44 } 45 else 46 temp[pos++]=str[i]; 47 48 } 49 } 50 return sheet[r][c]; 51 } 52 53 int main() 54 { 55 int t; 56 scanf("%d",&t); 57 while(t--) 58 { 59 scanf("%d%d",&col,&row); 60 memset(sheet,0,sizeof(sheet)); 61 62 for(int i=1;i<=row;i++) 63 for(int j=1;j<=col;j++) 64 { 65 cin>>str; 66 if(str[0]=='=') 67 { 68 sheet[i][j]=MARK; 69 formula[i][j]=str; 70 } 71 else 72 sheet[i][j]=atoi(str.c_str()); 73 } 74 75 for(int i=1;i<=row;i++) 76 for(int j=1;j<=col;j++) 77 if(sheet[i][j]==MARK) 78 { 79 dfs(i,j); 80 } 81 for(int i=1;i<=row;i++) 82 { 83 for(int j=1;j<=col;j++) 84 { 85 if(j!=1) 86 printf(" "); 87 printf("%d",sheet[i][j]); 88 } 89 printf("\n"); 90 } 91 } 92 return 0; 93 }
活在现实,做在梦里。

浙公网安备 33010602011771号