拓撲排序入門 基礎
阿新 • • 發佈:2018-08-11
while 之前 拓撲 %d string 其他 void ring math.h
其他說明:符合條件的排名可能不是唯一的,此時要求輸出時編號小的隊伍在前;輸入數據保證是正確的,即輸入數據確保一定能有一個符合要求的排名。 SampleInput
SampleOutput
早上學了拓撲排序中最基礎的一題,教的是用vector寫的 然後自己剛剛用鏈式前向星寫了一遍
拓撲排序就是先找出度為0的點然後放入隊列,再把與這個點相連的點的度減一,如果度變成了0就在放進隊列裏面,直到隊列變為空。
判斷這個圖是否無環 就用sum=0,每次進去就sum++,如果最後sum==n說明是無環的。
拓撲排序的裸題:
確定比賽名次
TimeLimit: 2000/1000 MS (Java/Others) MemoryLimit: 65536/32768 K (Java/Others) Problem Description 有N個比賽隊(1<=N<=500),編號依次為1,2,3,。。。。,N進行比賽,比賽結束後,裁判委員會要將所有參賽隊伍從前往後依次排名,但現在裁判委員會不能直接獲得每個隊的比賽成績,只知道每場比賽的結果,即P1贏P2,用P1,P2表示,排名時P1在P2之前。現在請你編程序確定排名。 Input 輸入有若幹組,每組中的第一行為二個數N(1<=N<=500),M;其中N表示隊伍的個數,M表示接著有M行的輸入數據。接下來的M行數據中,每行也有兩個整數P1,P2表示即P1隊贏了P2隊。 Output 給出一個符合要求的排名。輸出時隊伍號之間有空格,最後一名後面沒有空格。其他說明:符合條件的排名可能不是唯一的,此時要求輸出時編號小的隊伍在前;輸入數據保證是正確的,即輸入數據確保一定能有一個符合要求的排名。 SampleInput
4 3 1 2 2 3 4 3
1 2 4 3
第一種 vector寫法:
#include<stdio.h> #include<string> #include<string.h> #include<set> #include<queue> #include<math.h> #include<stack> #include<vector> #include<map> #include<cmath> #include<stdlib.h> #include<algorithm> usingnamespace std; #define ll long long #define mes(x,a) memset(x,a,sizeof(x)) const int maxn=1e3+3; const int inf=0x3f3f3f3f; vector<int>a[maxn]; int n,m; int degree[maxn]; void init() { mes(degree,0); for(int i=0; i<=n; i++) a[i].clear(); } void topo() { int i,j,t; priority_queue<int>que; for(int i=1; i<=n; i++) if(degree[i]==0) que.push(-i); int flag=1; while(!que.empty()) { if(!flag) printf(" "); if(flag) flag=0; int now=-que.top(); que.pop(); printf("%d",now); for(int i=0; i<a[now].size(); i++) { int y=a[now][i]; degree[y]--; if(degree[y]==0) que.push(-y); } } puts(""); } int main() { int i; while(scanf("%d%d",&n,&m)!=EOF) { init(); for(i=0; i<m; i++) { int u,v; scanf("%d%d",&u,&v); a[u].push_back(v); degree[v]++; } topo(); } return 0; }
第二種鏈式前向星寫法:
#include<stdio.h> #include<string> #include<string.h> #include<set> #include<queue> #include<math.h> #include<stack> #include<vector> #include<map> #include<cmath> #include<stdlib.h> #include<algorithm> using namespace std; const int maxn=1e3+5; int n,m; int first[maxn],sign; int degree[maxn]; struct Edge { int to; int w; int next; } edge[maxn]; void init() { sign=0; memset(first,-1,sizeof(first)); memset(edge,0,sizeof(edge)); } void add_edge(int u,int v,int w) { edge[sign].to=v; edge[sign].w=w; edge[sign].next=first[u]; first[u]=sign++; } void topo() { priority_queue<int,vector<int >, greater<int > >que; ///小根堆 for(int i=1; i<=n; i++) { if(degree[i]==0) que.push(i); } int flag=0; while(!que.empty()) { int now=que.top(); que.pop(); if(flag==1) { printf(" "); } flag=1; printf("%d",now); for(int i=first[now]; ~i; i=edge[i].next) { int to=edge[i].to; degree[to]--; ///與now相連的點的度減一,如果==1就放進隊列 if(degree[to]==0) { que.push(to); } } } puts(""); } int main() { while(~scanf("%d %d",&n,&m)) { init(); for(int i=1; i<=m; i++) { int u,v; scanf("%d %d",&u,&v); add_edge(u,v,1); degree[v]++;///度增加 } topo(); } }
拓撲排序入門 基礎