1. 程式人生 > >hdu 4857 反向拓撲模板題,入門

hdu 4857 反向拓撲模板題,入門

之前寫過的部落格,今天回頭看時,發現格式好亂,重新寫一下。 

  ---------------------------------------

分析

首先先處理特殊關係,對於有要求的數字,在他們倆之間建立一條邊,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;
}