拓撲相關題目
阿新 • • 發佈:2017-11-04
n個元素 有一個 計劃 div 技術分享 lose found logs true
有關拓撲一個挺直觀的圖:
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];View Codeint 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; }View Code
拓撲相關題目