有关拓扑一个挺直观的图:
1.luogu P1347 排序
思路:
题目中明确的提到:确定n个元素的顺序后即可结束程序,可以不用考虑确定顺序之后出现矛盾的情况。
所以我们可以每读入一个条件,就进行一遍Floyd,判断顺序的条件就是:
枚举i,然后用map数组记录一下比i要大的个数,如果n-sum==s+1(s+1的原因是因为我们是从0开始计数的),那么就用一个q数组记录下来
而如果在给出的n之内,只要有一个没有被确定,我们就不能够说已经排好序了
还有一点需要注意的是:
· 如果出现了map[i][i]=true的情况,则说明不合法,输出"Inconsistency found after x relations.",其中的x就是我们输入时所用到的i
坑点:
别忘了输出".",这个炒鸡重要!
上代码:
#include <iostream> #include <cstdio> using namespace std; const int E = 26; const char a[E]={‘A‘,‘B‘,‘C‘,‘D‘,‘E‘,‘F‘,‘G‘,‘H‘,‘I‘,‘J‘,‘K‘,‘L‘,‘M‘,‘N‘,‘O‘,‘P‘,‘Q‘,‘R‘,‘S‘,‘T‘,‘U‘,‘V‘,‘W‘,‘X‘,‘Y‘,‘Z‘}; int n,m; char b[5]; int q[E]; bool map[E][E]; int floyd() { for(int k=0; k<n; k++) for(int i=0; i<n; i++) for(int j=0; j<n; j++) if(map[i][k] && map[k][j]) map[i][j]=true; for(int i=0; i<n; i++) if(map[i][i]) return 2; //不合法 for(int s=0; s<n; s++) { //枚举顺序 int sum,x=-1; for(int i=0; i<n; i++) { sum=0; //有几个比i要大的 for(int j=0; j<n; j++) if(map[i][j]) sum++; if(n-sum==s+1) x=i; //匹配成功 } if(x==-1) return 0; //该位没有被确定 q[s]=x; } return 1; } int main() { scanf("%d%d",&n,&m); for(int i=1,u,v; i<=m; i++) { scanf("%s",b); u=b[0]-‘A‘,v=b[2]-‘A‘; map[u][v]=true; int p=floyd(); if(p==1) { printf("Sorted sequence determined after %d relations: ",i); for(int i=0; i<n; i++) printf("%c",a[q[i]]);printf("."); return 0; } else if(p==2) { printf("Inconsistency found after %d relations.",i); return 0; } } printf("Sorted sequence cannot be determined."); return 0; }
2.luogu P1137 旅行计划
思路:
用拓扑序列+dp来做
转移方程是 ans[v]=max(ans[v],ans[u]+1);(其中u的顺序为拓扑的顺序)
上代码:
#include <iostream> #include <cstdio> #include <queue> using namespace std; const int N = 100001; const int M = 200001; int n,m,u,v; int ans[N]; struct node { int next,to; }e[M]; int top,head[N]; void add(int u,int v) { top++; e[top].to=v; e[top].next=head[u]; head[u]=top; } queue<int>q; int ru[N],c[M]; void topo() { top=0; for(int i=1; i<=n; i++) if(!ru[i]) q.push(i); while(!q.empty()) { u=q.front(); q.pop(); c[++top]=u; for(int i=head[u]; i; i=e[i].next) { v=e[i].to; ru[v]--; if(!ru[v]) q.push(v); } } } int main() { scanf("%d%d",&n,&m); for(int i=1; i<=m; i++) { scanf("%d%d",&u,&v); add(u,v); ru[v]++; } topo(); for(int i=1; i<=n; i++) ans[i]=1; for(int x=1; x<=n; x++) { u=c[x]; for(int i=head[u]; i; i=e[i].next) { v=e[i].to; ans[v]=max(ans[v],ans[u]+1); } } for(int i=1; i<=top; i++) printf("%d\n",ans[i]); return 0; }
时间: 2024-10-08 22:06:23