• 正向与反向拓扑排序的区别(hdu 1285 确定比赛名次和hdu 4857 逃生)


    确定比赛名次

    Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 65536/32768K (Java/Other)
    Total Submission(s) : 16   Accepted Submission(s) : 9
    Problem Description
    有N个比赛队(1<=N<=500),编号依次为1,2,3,。。。。,N进行比赛,比赛结束后,裁判委员会要将所有参赛队伍从前往后依次排名,但现在裁判委员会不能直接获得每个队的比赛成绩,只知道每场比赛的结果,即P1赢P2,用P1,P2表示,排名时P1在P2之前。现在请你编程序确定排名。
     

     

    Input
    输入有若干组,每组中的第一行为二个数N(1<=N<=500),M;其中N表示队伍的个数,M表示接着有M行的输入数据。接下来的M行数据中,每行也有两个整数P1,P2表示即P1队赢了P2队。
     

    逃生

    Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 32768/32768K (Java/Other)
    Total Submission(s) : 20   Accepted Submission(s) : 9
    Problem Description
    糟糕的事情发生啦,现在大家都忙着逃命。但是逃命的通道很窄,大家只能排成一行。

    现在有n个人,从1标号到n。同时有一些奇怪的约束条件,每个都形如:a必须在b之前。
    同时,社会是不平等的,这些人有的穷有的富。1号最富,2号第二富,以此类推。有钱人就贿赂负责人,所以他们有一些好处。

    负责人现在可以安排大家排队的顺序,由于收了好处,所以他要让1号尽量靠前,如果此时还有多种情况,就再让2号尽量靠前,如果还有多种情况,就让3号尽量靠前,以此类推。

    那么你就要安排大家的顺序。我们保证一定有解。
     
    Input
    第一行一个整数T(1 <= T <= 5),表示测试数据的个数。 然后对于每个测试数据,第一行有两个整数n(1 <= n <= 30000)和m(1 <= m <= 100000),分别表示人数和约束的个数。 然后m行,每行两个整数a和b,表示有一个约束a号必须在b号之前。a和b必然不同。
     
    Output
    对每个测试数据,输出一行排队的顺序,用空格隔开。
     
    Sample Input
    1 5 10 3 5 1 4 2 5 1 2 3 4 1 4 2 3 1 5 3 5 1 2
     
    Sample Output
    1 2 3 4 5
     
     

    Output
    给出一个符合要求的排名。输出时队伍号之间有空格,最后一名后面没有空格。 其他说明:符合条件的排名可能不是唯一的,此时要求输出时编号小的队伍在前;输入数据保证是正确的,即输入数据确保一定能有一个符合要求的排名。
     

    Sample Input
    4 3 1 2 2 3 4 3
     

    Sample Output
    1 2 4 3
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
    题解
    两者看着并没什么大的区别。
    但前者是用最普通的拓扑排序,而后者需要反着来。
     
    对普通的拓扑排序,由于题目需要按序,所以使用优先队列即可,将没有 前点 (即入度)的点入列,用这几个点的路径减少其他点的入度,然后将入度为0的入队,就行了。
     
    而对于第二题,则由于要求的不同(先考虑1在尽量前,再考虑2尽量前。。。),我们将后点设为入度,同样的方法排序,反向输出即可。
     
    可能有人会觉得两者差不多。
    这里给个例子。
     
    5 2(n,m)
    5 1 
    4 2

    正向给出的答案是3 4 2 5 1 
    反向给出的答案是1 2 3 4 5 
     
    理解一下
     
    以下是代码:
    1285 确定比赛名次:
    #include<bits/stdc++.h>
    #define INF 0x3f3f3f3f
    #define me(a,b) memset(a,b,sizeof(a))
    #define N 5100
    typedef long long ll;
    using namespace std;
    
    int in[N],head[N],n,m,cnt,s,e;
    priority_queue<int,vector<int>,greater<int> > q;
    vector<int> ans;
    
    struct co
    {
          int e,pre;
    }mp[N];
    
    void init()
    {
          me(head,-1);
          cnt=0;
          me(in,0);
          while(!q.empty())
                q.pop();
          ans.clear();
    }
    
    void add(int ss,int ee)
    {
          mp[cnt].e=ee;
          mp[cnt].pre=head[ss];
          head[ss]=cnt++;
    }
    
    int main()
    {
        //freopen("in.txt","r",stdin);
        while(~scanf("%d%d",&n,&m))
        {
              init();
              while(m--)
              {
                      scanf("%d%d",&s,&e);
                    in[e]++;
                    add(s,e);
              }
              for(int i=1;i<=n;i++)
              {
                    if(in[i]==0)
                    {
                          q.push(i);
                    }
              }
              while(!q.empty())
              {
                    int f=q.top();
                      ans.push_back(f);
                    q.pop();
                    for(int i=head[f]; i!=-1; i=mp[i].pre)
                    {
                          in[mp[i].e]--;
                          if(in[mp[i].e]==0)
                          {
                                  q.push(mp[i].e);
                          }
                    }
    
              }
              for(int i=0;i<ans.size();i++)
              {
                    if(i)
                      cout<<' ';
                    cout<<ans[i];
              }
              cout<<endl;
        }
    }

    4857:

    #include<bits/stdc++.h>
    #define INF 0x3f3f3f3f
    #define me(a,b) memset(a,b,sizeof(a))
    #define N 100010
    typedef long long ll;
    using namespace std;
    
    int in[30100],head[N],n,m,cnt,s,e;
    priority_queue<int> q;
    vector<int> ans;
    
    struct co
    {
          int e,pre;
    }mp[N];
    
    void init()
    {
          me(head,-1);
          me(in,0);
          cnt=0;
          while(!q.empty())
                q.pop();
          ans.clear();
    }
    
    void add(int ss,int ee)
    {
          mp[cnt].e=ee;
          mp[cnt].pre=head[ss];
          head[ss]=cnt++;
    }
    
    int main()
    {
        //freopen("in.txt","r",stdin);
        int T;
        cin>>T;
        while(T--)
        {
              init();
              scanf("%d%d",&n,&m);
              while(m--)
              {
              scanf("%d%d",&s,&e);
                    in[s]++;
                    add(e,s);
              }
              for(int i=1;i<=n;i++)
              {
                    if(in[i]==0)
                    {
                          q.push(i);
                    }
              }
              while(!q.empty())
              {
                    int f=q.top();
                      ans.push_back(f);
                    q.pop();
                    for(int i=head[f]; i!=-1; i=mp[i].pre)
                    {
                          in[mp[i].e]--;
                          if(in[mp[i].e]==0)
                          {
                                  q.push(mp[i].e);
                          }
                    }
    
              }
              for(int i=ans.size()-1;i>-1;i--)
              {
                    cout<<ans[i];
                    if(i)
                      cout<<' ';
              }
              cout<<endl;
        }
    }
     
  • 相关阅读:
    使用一系列命令生成字母数字符号组合
    linux分析apache日志获取最多访问的前10个IP
    shell脚本输出九九乘法表
    shell脚本输出空心等腰三角形
    awk与sed命令面试题整理
    linux分析apache日志获取最多访问的前10个IP
    iOS开发-由浅至深学习block
    PM常用软件&工作平台
    iOS开发之—— 各种加密的使用(MD5,base64,DES,AES,RSA,DSA)
    MVVM With ReactiveCocoa
  • 原文地址:https://www.cnblogs.com/zgncbsylm/p/10727395.html
Copyright © 2020-2023  润新知