拓扑排序
算法思想
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;
}