2016京勝杯-喫在工大(拓撲排序)

題目描述

JH和他的好朋友YZ兩名程序員回訪母校合工大,準備在這住一段日子,都說“玩在安大,喫在工大”,JH又是一名典型喫貨,於是決定在工大食堂好好喫一段日子,但是,面對美食誘惑:黃燜雞、風暴乾鍋、麻辣香鍋、奧爾良烤翅…由於時間有限,JH不知道哪頓飯喫哪個菜好。 於是YZ爲了幫助他解決這個問題,也順便考考他,給他出了一個問題:“黃燜雞必須在乾鍋花菜前面喫,乾鍋牛肉必須在乾鍋魷魚前面喫….你按這個要求下,就知道喫的順序啦”。JH抓抓頭,分分鐘寫了個程序搞定,現在,讓你來寫寫看?輸出一組JH符合條件下喫的食物的序列。 假設JH每頓只吃一種食物,且每頓喫的都不同,食物編號1到N。

輸入

先輸入一個整數T,表示T(T < 50)組數據。 每組數據第一行輸出一個整數,N,M,分別表示有N種食物,總共有M個約束條件,接下來M行每行輸入兩個正整數a,b( n > = a > 0,n > = b > 0),表示食物a必須在食物b之前喫。

輸出

各組數據輸出答案佔一行,輸出一組符合條件的序列(要求輸出字典序最大的那一組),如果答案不存在,輸出“-1”。

樣例輸入

1
4 3
1 2
2 3
4 3

樣例輸出

4 1 2 3

思路

此題主要運用拓撲排序

  1. 首先讀取數據,存入一個圖中,同時記錄每個節點的入度;
  2. 然後再將入度爲0的節點加入都優先隊列中;
  3. 取優先隊列的隊首元素,並將此元素存到數組result中,然後依次遍歷此節點的鄰接點,同時將鄰接點的入度減1,並將鄰接點中入度爲0的加入到優先隊列中;
  4. 重複步驟三,直到隊列爲空;

code

#include <iostream>
#include <queue>
#include <cstring>
#include <fstream>
using namespace std;

int G[1005][1005];
bool vis[1005];
int n, m;

bool isStart(int k)
{
    for(int i = 0; i <= n; i ++)
    {
        if(G[i][k])
        {
            return false;
        }
    }
    return true;
}

bool hasHoop()
{
    for(int i = 1; i <= n; i ++)
    {
        if(!vis[i])
        {
            return true;
        }
    }
    return false;
} 

void Do()
{
    priority_queue<int> pq;
    int loc = 0;
    int ans[1005];
    for(int i = 1; i <= n; i++)
    {
        if(isStart(i))
        {
            pq.push(i);
        }
    }
    while(!pq.empty())
    {
        //cout << "11" << endl;
        int k = pq.top();
        pq.pop();
        if(vis[k])
        {
            continue;
        }
        ans[loc++] = k;
        vis[k] = true;
        for(int i = 1; i <= n; ++ i)
        {
            G[k][i] = 0;
            if(isStart(i))
            {
                pq.push(i);
            }
        }
    }
    if(hasHoop())
    {
        cout << "-1" << endl; 
    }
    else
    {
        for(int i = 0; i < n; i ++)
        {
            if(i)
            {
                cout << " ";
            }
            cout << ans[i];
        }
        cout << endl;
    }
}

int main()
{
    std::ios::sync_with_stdio(false);
    std::cin.tie(0);
    //ifstream cin("data.in");
    int T;
    cin >> T;
    while(T --)
    {
        cin >> n >> m;
        memset(G, 0, sizeof(G));
        memset(vis, false, sizeof(vis));
        for(int i = 0; i < m; i ++)
        {
            int a, b;
            cin >> a >> b;
            G[a][b] = 1;
        }
        Do();
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章