拓撲排序
算法思想
1.入度數組ru[],記錄是否存在環的情況;
2.利用bfs()將入度爲0的依次壓入隊列,將其所指向的點入度減一;
3.在排序的過程中實現題目目的;
例題
HDU2647
思路:
1.先反向建邊,x比y多則將y指向x;
2.用一個val[]數組記錄每一個點最大需要多花費的錢,依次向上更新,排序的過程就完成了,數據的更新;
## 代碼
#include <bits/stdc++.h>
using namespace std;
const int N=1e5+55;
int head[N],ru[N],val[N];
int ans,cnt,n,m;
struct node{
int to,next;
}mp[N];
void add(int x, int y)
{
mp[cnt].to=y;
mp[cnt].next=head[x];
head[x]=cnt++;
}
bool tuop()
{
queue<int >q;
int t=0;
for(int i=1;i<=n;++i){
if(!ru[i]){
q.push(i);
val[i]=0;
}
}
while(!q.empty()){
int u=q.front();
q.pop();
ans=ans+val[u]+888; //沒有點指向該點了,直接算出所需費用;
++t; //記錄是否有環的變量;
for(int i=head[u];~i;i=mp[i].next){
int to=mp[i].to;
val[to]=max(val[to],val[u]+1); //要取最大值,畫圖易得;
ru[to]--;
if(!ru[to]){
q.push(to);
}
}
}
if(t!=n) return false;
return true;
}
int main()
{
while(scanf("%d%d",&n,&m)!=EOF){
int x,y;
ans=cnt=0;
memset(head,-1,sizeof(head));
memset(ru,0,sizeof(ru));
memset(val,-1,sizeof(val));
for(int i=0;i<m;++i){
scanf("%d%d",&x,&y);
add(y,x);
ru[x]++;
}
bool k=tuop();
if(k){
printf("%d\n",ans);
}
else{
printf("-1\n");
}
}
return 0;
}