• PKU 3687 Labeling Balls(拓扑排序)


    题目大意:原题链接

    给出N个未编号的质量各不相同的球,以及它们质量轻重的大小关系,给它们从1~N贴标签编号,无重复。问是否存在可行的编号方法,不存在输出-1,

    如果存在则输出唯一一种方案,此方案是使得编号小的球的重量尽量轻,先是编号为1的重量要最轻,其次比编号2,以此类推......

    思路:当解有多组时,编号小的质量尽量小。所以就采用逆拓扑排序(正向的贪心不能完全保证序号小的节点尽量排在前面。仔细思考~~~~~)

    按编号从大到小,找质量最大的。这样,小标签就都留给了质量小的。比如4-->1,3-->2这个图(答案是2 4 3 1),

    如果正向的话先出来的是3,然后是2,然后是4,最后才是1,输出(3 2 4 1)是个反例,而反向的话却可以保证把小的尽可能留给小标号的

    解法一:逆拓扑排序+贪心

    #include<cstdio>
    #include<cstring>
    #define maxn 210
    using namespace std;
    int n,m,out[maxn],q[maxn];
    int i,j,k,graph[maxn][maxn];
    
    bool Toposort(){
        for(i=n;i>=1;i--){//按编号从大到小
            for(j=n;j>=1;j--){//找质量最大的
                if(!out[j]){
                    q[j]=i;
                    out[j]=-1;
                    break;
                }
            }//j未通过break退出循环,说明无零出度节点,有环
            if(j<1) return false;
            for(k=1;k<=n;k++){
                if(graph[k][j]) 
                    out[k]--;
            }
        }
        return true;
    }
    
    int main(){
        int T,u,v;
        scanf("%d",&T);
        while(T--){
            scanf("%d%d",&n,&m);
            memset(graph,0,sizeof(graph));
            memset(out,0,sizeof(out));
            for(i=0;i<m;i++){
                scanf("%d%d",&u,&v);
                if(!graph[u][v]){
                    graph[u][v]=true;
                    out[u]++;
                }//注意重边 
            }
            if(Toposort()){
                for(i=1;i<=n;i++){
                    if(i!=n) printf("%d ",q[i]);
                    else printf("%d
    ",q[i]);
                }
            }
            else printf("-1
    ");
        }                                                             
    }

    解法二:逆拓扑排序+优先队列

    #include<cstdio>
    #include<queue> 
    #include<cstring>
    #define maxn 210
    using namespace std;
    int n,m,out[maxn],va[maxn];
    int graph[maxn][maxn];
    priority_queue<int> que;
    bool Toposort()
    {
        for(int i=1;i<=n;i++){
            if(!out[i])
                que.push(i);
        }
        if(que.empty()) return false;//注意 
        int t=n;
        while(!que.empty()){
            int j=que.top();
            que.pop();
            va[j]=t--;
            for(int k=1;k<=n;k++){
                if(graph[k][j]){
                    graph[k][j]=0;
                    out[k]--;
                    if(!out[k]) 
                        que.push(k);
                } 
            }
        }
        if(t) return false;//注意 
        return true;
    }
    
    int main()
    {
        int T,u,v;
        scanf("%d",&T);
        while(T--){
            scanf("%d%d",&n,&m);
            memset(graph,0,sizeof(graph));
            memset(out,0,sizeof(out));
            for(int i=0;i<m;i++){
                scanf("%d%d",&u,&v);
                if(!graph[u][v]){
                    graph[u][v]=true;
                    out[u]++;
                }//注意重边 
            }
            if(Toposort()){
                for(int i=1;i<n;i++)
                    printf("%d ",va[i]);
                printf("%d
    ",va[n]);
            }
            else printf("-1
    ");
        }                                                             
    }
  • 相关阅读:
    区间DP中的环形DP
    hdu 5251 包围点集最小矩形 ***
    hdu 4858 水题
    hdu 3530 单调队列 **
    hdu 3338 最大流 ****
    hdu 2732 最大流 **
    hdu 5233 离散化 **
    hdu 3555 数位dp *
    zoj 3469 区间dp **
    2015 安徽程序设计省赛总结
  • 原文地址:https://www.cnblogs.com/freinds/p/6411696.html
Copyright © 2020-2023  润新知