POJ - 3687 Labeling Balls (拓扑排序)

题意:N个点,给出M条两个点u、v,满足u比值小。给这N个点编号,要求排在前的比排在后的质量小,且编号不重复。求每点能得到最小编号的编号方法。

分析:用拓扑排序求解。

用优先队列来存待标记的点,编号大的点优先出队列,然后从大到小依次标记(编号小的优先肯定是错的,当时wa死了)。

若求不出拓扑排序则答案无解。

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
#include<queue>
typedef long long LL;
using namespace std;
const int maxn =5e2+5;
const int maxm = 4e4+5;
struct Edge{
    int v,next;
}edge[maxm];
int head[maxn],tot,cnt;
int ind[maxn];
void init()
{
    memset(ind,0,sizeof(ind));
    memset(head,-1,sizeof(head));
    tot=0;
}

void AddEdge(int u,int v)
{
    edge[tot] = (Edge){v,head[u]};
    head[u] = tot++;   
}

int ans[maxn];
bool topo(int n)
{
    cnt=n;
    priority_queue<int> Q;
    for(int i =1;i<=n;++i){
        if(!ind[i]){
            Q.push(i);
        }
    }
    while(!Q.empty()){
        int u = Q.top() ;Q.pop();
        ans[u] = cnt--;
        for(int i=head[u];~i;i=edge[i].next){
            int v = edge[i].v;
            ind[v]--;
            if(!ind[v]){
                Q.push(v);
            }
        }
    }
    if(cnt!=0) return false;
    else return true;
}
int main()
{
    #ifndef ONLINE_JUDGE
        freopen("in.txt","r",stdin);
        freopen("out.txt","w",stdout);
    #endif
    int N,M,m,q,u,v,cas=1;
    int T; scanf("%d",&T);
    while(T--){
        init();
        bool flag = false;
        scanf("%d%d",&N,&M);
        while(M--){
            scanf("%d%d",&v,&u);
            //if(u==v) flag = true;
            AddEdge(u,v);
            ind[v]++;
        }
        if(flag || !topo(N)) printf("-1\n");
        else{
            for(int i=1;i<N;++i){
                printf("%d ",ans[i]);
            }
            printf("%d\n",ans[N]);
        }
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/xiuwenli/p/9497669.html