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;



    }



}


 


 

你可能感兴趣的:(HDU)