1. 程式人生 > >hdu 4857 逃生(拓撲排序)

hdu 4857 逃生(拓撲排序)

        題意:給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;
}