1. 程式人生 > >HDu4857逃生 反向拓撲排序來出字典序最小解

HDu4857逃生 反向拓撲排序來出字典序最小解

糟糕的事情發生啦,現在大家都忙著逃命。但是逃命的通道很窄,大家只能排成一行。

現在有n個人,從1標號到n。同時有一些奇怪的約束條件,每個都形如:a必須在b之前。

同時,社會是不平等的,這些人有的窮有的富。1號最富,2號第二富,以此類推。有錢人就賄賂負責人,所以他們有一些好處。

負責人現在可以安排大家排隊的順序,由於收了好處,所以他要讓1號儘量靠前,如果此時還有多種情況,就再讓2號儘量靠前,如果還有多種情況,就讓3號儘量靠前,以此類推。

那麼你就要安排大家的順序。我們保證一定有解。

    Input
    第一行一個整數T(1 <= T <= 5),表示測試資料的個數。 

然後對於每個測試資料,第一行有兩個整數n(1 <= n <= 30000)和m(1 <= m <= 100000),分別表示人數和約束的個數。

然後m行,每行兩個整數a和b,表示有一個約束a號必須在b號之前。a和b必然不同。

    Output
    對每個測試資料,輸出一行排隊的順序,用空格隔開。
   **分析**
   		首先先處理特殊關係,對於有要求的數字,在他們倆之間建立一條邊,a->b 同時b的入度++,表示b的限制條件增加1.那麼在處理時,用一個優先佇列按照greater的順序push,(push入度為0)那麼這道題就得到解決了,然後在這道題中是行不通的,因為對於這樣一組資料3 1一共有5個點的情況下,那麼按照上面的方法那麼就會輸出2 3 1,然而這並不符合題意因為題目中要求是1要儘可能上前,因該輸出的是3 1 2,那麼該如何處理這個問題喃?首先應該分析為什麼會出現這個問題,是因為在優先佇列《greater》下因為2的入度為0,所以會先入隊,那麼應該怎麼讓3先入隊?大家都是入隊為0,並且老子還抱著個大腿啊喂!於是就考慮到反向拓撲,然後當然也要反向建圖是不是。優先佇列也要按照less的順序排序,這樣做的結果是5 4 2 1 3然後再反向輸出就GG了,不要忘記重邊的判斷哦。
   		程式碼:
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<set>
#include<stack>
#include<cstring>
#include<vector>
#include<queue>

using namespace std;

const int maxn = 3e4+10;
int in[maxn];
int n, m;
stack<int>iron;
vector<int>vec[maxn];
typedef pair<int, int>pii;

void ini()
{
		memset(in, 0, sizeof(in));
		for (int i = 0; i <= n; i++)
				vec[i].clear();
		while (!iron.empty())
				iron.pop();
}

void solve()
{
		priority_queue <int, vector<int> >que;
		for (int i = 1; i <= n; i++)
		{
				if (in[i] == 0)
						que.push(i);
		}
		while (!que.empty())
		{
				int t = que.top();
				iron.push(t);
				que.pop();
				for (int i = 0; i < vec[t].size(); i++)
				{
						int p = vec[t][i];
						if (--in[p] == 0)
								que.push(p);
				}
		}
}

void show()
{
		while (iron.size() > 1)
		{
				printf("%d ", iron.top());
				iron.pop();
		}
		printf("%d\n", iron.top());
}

int main()
{
		int t;
		scanf("%d", &t);
		while (t--)
		{
				scanf("%d %d", &n, &m);
				ini();
				set<pii>s;
				for (int i = 0; i < m; i++)
				{
						int a, b;
						scanf("%d %d", &a, &b);
						pii p = make_pair(b, a);
						if (s.count(p) == 0)
						{
								s.insert(p);
								vec[b].push_back(a);
								in[a]++;
						}
				}
				solve();
				show();
		}
	//	system("pause");
		return 0;
}