http://acm.hdu.edu.cn/showproblem.php?pid=2647
//逆拓扑排序 ,首先常规思路是从入度为0的点开始向后推,但是你不知道后面会有多少个入度不一样的点,那么换一种思路,如果从后往前推,是不是就能解决问题。
这里 盗用一张图,
上图分成3个层次,那么第三层每个人的需求都是888,往上一层,就加1,把最下一层当成入度为0的点,逆推上去。因为边比较多,可以用vector来表示邻接表。
#include<cstdio>
#include<vector>
#include<queue>
#include<cstring>
#define N 10001
using namespace std;
int in[N],mark[N],n,m;
vector<int>v[20001];
void init()
{
memset(in,0,sizeof(in));
memset(mark,0,sizeof(mark));
for(int i=0;i<N;i++)
v[i].clear();
}
void top_sort()
{
queue<int>q;
for(int i=1;i<=n;i++)
if(in[i]==0)
{
q.push(i); //把入度为0的点放入队列
mark[i]=888; //初始值为888
}
while(!q.empty())
{
int t=q.front();
q.pop();
for(int i=0;i<v[t].size();i++)
{
in[v[t][i]]--; //删边
if(in[v[t][i]]==0)
{
mark[v[t][i]]=mark[t]+1; //并且向上一层,权值加1
q.push(v[t][i]);
}
}
}
for(int i=1;i<=n;i++)
{
if(in[i]!=0) //如果某一点入度不为0 表示构成环
{
printf("-1\n");
return;
}
}
int s=0;
for(int i=1;i<=n;i++)
s+=mark[i];
printf("%d\n",s);
//return;
}
int main()
{
int a,b;
while(scanf("%d%d",&n,&m)!=EOF)
{
init();
for(int i=1;i<=m;i++)
{
scanf("%d%d",&a,&b);
in[a]++; //a的入度加加
v[b].push_back(a); //有向图
}
top_sort();
}
return 0;
}