P3243 [HNOI2015]菜餚製做

萌新今天剛剛接觸拓撲排序,找到了一些題,而後就來作這道題紫題了(霧)html

仍是不要被題目的難度嚇到吧,其實這道題挺模板的,思路感受也比較好想,可是關於證實這些,我太菜,並不會。是一道很是好的入手拓撲排序的題,不像其餘題目那樣難想node

對於一個限制 <i,j>,其實表示的就是 i 必須在 j 以前完成,咱們把這個條件轉化成圖的形式就是 i 到 j 有一條有向邊,而後就能夠試着往拓撲排序的方向思考了c++

拓撲排序最基礎的應用是什麼,能夠把它當作學習一個東西(好比語文吧),你要學習一篇文章,你總得先學會認字吧,學會認字確定就要學會拼音,那麼你要提早學習的東西就是前置知識,就至關於以上提到的 j (你要完成 j ,你必須先學會 i )。那這麼一看,裸裸的拓撲排序數組

可是有一點變化的是什麼呢?題目中的編號越小,表示它的預估質量越高(顯而易見,這裏指的不是字典序),因此對於編號小的,咱們但願它在前面,而編號的就日後面放oop

由於若是正序按題目建邊的話,假如1號點的入度不爲1,而2的入度爲0,咱們應該先把限制1的點所有刪掉,再把1弄出來,再去刪2,這樣才能保證最優,可是正序直接創建的話咱們會把2直接刪去學習

因此咱們應該倒序創建。咱們能夠經過大根堆來實現把編號越大的越先處理,而後再倒序輸出答案就能夠了(能夠理解爲先把價值低的存儲下來,價值高的就在後面,這個時候倒序輸出就能夠保證價值越高的越先作)spa

而後剩下了一個 Impossible ,這個也很簡單,拓撲排序的另一種應用,判斷是否有環存在就能夠了.net

#include<bits/stdc++.h>
using namespace std;
const int MAXN=500000;
int d;
int n,m;
int head[MAXN],tot;
struct node{
	int net,to;
}e[MAXN];
void add(int x,int y){
	e[++tot].to=y;
	e[tot].net=head[x];
	head[x]=tot;
} //鏈式前向星存儲邊,鄰接矩陣通常來講會慢一點 
int ru[MAXN]; //入度 
int ans[MAXN],now; //存儲答案 
bool toop(){  //直接寫成bool類型容易判斷一些 
	priority_queue<int>q; //堆(優先隊列) STL確實很方便 
	for(register int i=1;i<=n;i++){
		if(ru[i]==0) q.push(i); //入度爲0的加入堆 
	}
	while(!q.empty()){
		int x=q.top();
		q.pop();
		ans[++now]=x; //存儲答案 
		for(register int i=head[x];i;i=e[i].net){
			ru[e[i].to]--; //這個點刪去了,它能到的點的入度就要-- 
			if(ru[e[i].to]==0){ //入度爲0的加入堆中 
				q.push(e[i].to);
			} 
		}
	}
	if(now==n) return true; //若是恰好處理了n個,說明沒有環 
	return false; //不然有環,出錯 
}
int main(){
	scanf("%d",&d);
	while(d--){
		now=0,tot=0;
		for(register int i=1;i<=n;i++) ru[i]=0,ans[i]=0;
		memset(e,0,sizeof e);
		memset(head,0,sizeof head); //注意清空數組,建議你們本身若是能手動清空就別用memset 
		scanf("%d%d",&n,&m);
		for(register int i=1;i<=m;i++){
			int x,y;
			scanf("%d%d",&x,&y);
			add(y,x);
			ru[x]++; //靈魂的反向建邊 
		}
		//bool k=toop(); 
		//這個地方挺玄學的吧,我最開始聲明瞭一個新變量判斷是否有環(如上) 
		//而後它就超時了,因此這裏直接寫成toop()直接判斷就能夠了 
		if(toop()==false) puts("Impossible!"); //若是有環就不可能 
		else{
			for(register int i=now;i>=1;i--) printf("%d ",ans[i]); //倒序輸出答案 
			puts("");
		}
	}
	return 0;
}

關於拓撲排序的一些具體介紹,你們能夠去看看 洛穀日報 快速入手拓撲排序這不會被算做抄襲吧) ,而後宣傳一下本身同桌的博客code

相關文章
相關標籤/搜索