1. 程式人生 > >拓撲排序入門 基礎

拓撲排序入門 基礎

while 之前 拓撲 %d string 其他 void ring math.h

早上學了拓撲排序中最基礎的一題,教的是用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
SampleOutput
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>
using
namespace 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();
    }
}

拓撲排序入門 基礎