逃生 HDU 4857(反向建圖 + 拓撲排序)

逃生

Problem Description 糟糕的事情發生啦,如今你們都忙着逃命。可是逃命的通道很窄,你們只能排成一行。php

如今有n我的,從1標號到n。同時有一些奇怪的約束條件,每一個都形如:a必須在b以前。
同時,社會是不平等的,這些人有的窮有的富。1號最富,2號第二富,以此類推。有錢人就賄賂負責人,因此他們有一些好處。ios

負責人如今能夠安排你們排隊的順序,因爲收了好處,因此他要讓1號儘可能靠前,若是此時還有多種狀況,就再讓2號儘可能靠前,若是還有多種狀況,就讓3號儘可能靠前,以此類推。測試

那麼你就要安排你們的順序。咱們保證必定有解。spa

Input 第一行一個整數T(1 <= T <= 5),表示測試數據的個數。 而後對於每一個測試數據,第一行有兩個整數n(1 <= n <=
30000)和m(1 <= m <= 100000),分別表示人數和約束的個數。code

而後m行,每行兩個整數a和b,表示有一個約束a號必須在b號以前。a和b必然不一樣。排序

Output 對每一個測試數據,輸出一行排隊的順序,用空格隔開。隊列

Sample Input
1
5 10
3 5
1 4
2 5
1 2
3 4
1 4
2 3
1 5
3 5
1 2
 

Sample Output
1 2 3 4 5

We have carefully selected several similar problems for you: 6742
6741 6740 6739 6738ip

思路

  • 題意:有咱們一個由 1~n 組成的有無環圖,在知足邊的指向(即:約束條件)的狀況下 儘量的 把 1 放在序列的前邊,而後子啊在 1放前邊的基礎上儘量的把2放前邊,,,,,,,這樣 拍出一個序列,注意:這裏的排序依照的規則必定不是 「字典序」 排序的規則
  • 分析:反向建圖 + 優先級隊列拓撲排序 + 倒敘輸出ans,,經過在題目上的所給的關係來反向建圖的話,因爲咱們的使用的 priorith_queue < int> 來實現的拓撲排序,那麼在逆向建圖以後,咱們必定能夠保證的 數字值大的且出度爲零的 點 必定是,會被 從優先級隊列中取出來,而後被壓入 ans 中 那麼小的值 會被最後壓入 ans,,,,因此最後要逆序輸出。。

代碼

#include<iostream>
#include<cstdio>
#include<queue>
#include<vector>
using namespace std;

const int Len = 30005;
vector<int> edge[Len], ans;
int n, m;
int in[Len];    //表示圖中度某個點的入度

void Solve()
{
    priority_queue<int> q;          //優先級隊列,權值大的會被放在前面
    for(int i = 1; i <= n; i ++)
        if(! in[i])
            q.push(i);
    int u, v;
    while(! q.empty())
    {
        u = q.top(); q.pop();
        ans.push_back(u);
        //減小與u相連的點v的入度
        for(int i = 0; i < edge[u].size(); i ++)
        {
            v = edge[u][i];
            if(-- in[v] == 0)
            {
                q.push(v);
            }
        }
    }
    for(int i = ans.size() - 1; i >= 0; i --)
        if(i)
            printf("%d ", ans[i]);
        else
            printf("%d", ans[i]);
    printf("\n");
}

void init()
{
    for(int i = 0; i <= n; i ++)
    {
        edge[i].clear();
        in[i] = 0;
    }
    ans.clear();
}

int main()
{
    /* freopen("A.txt","r",stdin); */
    /* freopen("Ans.txt","w",stdout); */
    int t;
    scanf("%d", &t);
    while(t --)
    {
        scanf("%d %d", &n, &m);
        init();
        int u, v;
        for(int i = 1; i <= m; i ++)
        {
            scanf("%d %d", &u, &v);
            edge[v].push_back(u);
            in[u] ++;
        }
        Solve();
    }

    return 0;
}
相關文章
相關標籤/搜索