HDU-2647拓扑排序

这道题不能用矩阵表示,因为1w*1w绝对超内存,分析数据,前一个a的钱要多于后一个b,所以我们要把b作为出度,a为入度,如果不明白这个地方,举例:b——>a——>c——>d ,b为888,钱数逐渐上升,如果反过来a为出度就不符合题意啦。。。

还有一个地方需要注意:判断输出-1的情况不能只判断没有一个入度为0的点,因为有可能在中间就出现矛盾了,如:a——>b——>c——>d——>c 有入度为0的点,但却要输出-1;


#include<iostream>
#include<cstring>
#include<queue>
#include<cstdio>
using namespace std;
#define MAX 10005
int n,sum,ans;
int into[MAX],head[MAX],money[MAX];
struct Reward
{
    int to;
    int next;
} edge[2*MAX];
void topu()
{
    int i,j,l,v;
    queue<int>Q;
    for(i=1; i<=n; i++)
        if(into[i]==0)
            Q.push(i);//把入度为0的点压如队列
    while(!Q.empty())
    {
        v=Q.front();//调用首位元素
        sum+=money[v];
        Q.pop();//出队
        ans++; //用一个变量记录调用元素的总量,最后与n作比较
        for(l=head[v]; l!=-1; l=edge[l].next)//与队首元素v有关的都枚举一遍
        {
            if(--into[edge[l].to]==0)//如果入度-1为0,即为v的下一个元素
            {
                Q.push(edge[l].to);//将其压入队列
                money[edge[l].to]=money[v]+1;//保证后一个要比前一个多1
            }
        }

    }
}
int main()
{
    int m,a,b,tot;
    while(scanf("%d%d",&n,&m)!=EOF)
    {

        memset(head,-1,sizeof(head));
        memset(into,0,sizeof(into));
        for(int i=1; i<=n; i++)
            money[i]=888;//所有人一开始都为888
        tot=0;
        sum=0;
        ans=0;
        while(m--)
        {
            scanf("%d%d",&a,&b);//注意要逆过来,因为后一个b是基础的888,应当作为出度
            edge[tot].to=a;
            edge[tot].next=head[b];
            head[b]=tot++;
            into[a]++;//记录入度
        }
        topu();
        if(ans!=n)//有可能在中间出现矛盾,必须保证每个地方都不矛盾
            sum=-1;
        cout<<sum<<endl;

    }

}



原文地址:https://www.cnblogs.com/riskyer/p/3290183.html