hdu 4857 逃生(拓扑排序)

来源:互联网 发布:windows系统常用命令 编辑:程序博客网 时间:2024/05/17 08:47

        题意:给n个人,他们之间存在前后关系,某人必须在某人前面;如果两个人之间不存在关系,则编号小的在前面,输出符合条件的顺序。

        思路:开始的想法是建单向图,按照拓扑排序,每次把入度为0的点加入到优先队列里面,测试通过,提价wa。想不明白为什么会wa,看了下discuss里面给出的样例,发现对于两个没有关系的点,编号小的必须在编号大的前面。

        3 2

        3 1

        3 1

        应该输出的是3 1 2,而不是2 3 1。这样的话就应该改为逆向建图,逆序输出,其他地方不变。提交之后AC。

#include<stdio.h>#include<string.h>#include<queue>using namespace std;const int N=30005;const int M=100005;struct edge{    int son;    int next;} Edge[M];int head[N],mark[N],ans[N];int cnt;int n,m;void AddEdge(int x,int y){    Edge[cnt].son=y,Edge[cnt].next=head[x],head[x]=cnt++;    return ;}void topo(){    priority_queue< int >q;    for(int i=1; i<=n; i++)    {        if(!mark[i])            q.push(i);    }    int k=0;    while(!q.empty())    {        int father=q.top();        q.pop();        ans[k++]=father;        for(int i=head[father]; i!=-1; i=Edge[i].next)        {            int son=Edge[i].son;            mark[son]--;            if(!mark[son])q.push(son);        }    }    return ;}int main(){    int T;    scanf("%d",&T);    while(T--)    {        scanf("%d%d",&n,&m);        memset(head,-1,sizeof(head));        memset(mark,0,sizeof(mark));        cnt=1;        for(int i=1; i<=m; i++)        {            int x,y;            scanf("%d%d",&x,&y);            AddEdge(y,x);            mark[x]++;        }        topo();        for(int i=n-1; i>0; i--)            printf("%d ",ans[i]);        printf("%d\n",ans[0]);    }    return 0;}


0 0