zoukankan      html  css  js  c++  java
  • 正向与反向拓扑排序的区别(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;
        }
    }
     
  • 相关阅读:
    【数学】三分法
    【数学】【背包】【NOIP2018】P5020 货币系统
    【数学】【CF27E】 Number With The Given Amount Of Divisors
    【单调队列】【P3957】 跳房子
    【极值问题】【CF33C】 Wonderful Randomized Sum
    【DP】【CF31E】 TV Game
    【神仙题】【CF28D】 Don't fear, DravDe is kind
    【线段树】【CF19D】 Points
    【字符串】KMP字符串匹配
    【二维树状数组】【CF10D】 LCIS
  • 原文地址:https://www.cnblogs.com/zgncbsylm/p/10727395.html
Copyright © 2011-2022 走看看