拓撲排序

拓撲排序

算法思想

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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章