zoukankan      html  css  js  c++  java
  • UESTC_排名表 2015 UESTC Training for Graph Theory<Problem I>

    I - 排名表

    Time Limit: 3000/1000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others)
     

    暑假前集训已经过了一半了,我们将会把当前排名公布出来。但是此刻秋实大哥却心急火燎,因为他不慎把排名删除了。

    一共有n个人参加排名,每个人都有一个名次,没有哪两个人的名次是相同的。现在秋实大哥掌握的一些情报,比如Ai的名次要先于Bi。(编号从1开始)

    你能帮秋实大哥恢复出排名表吗?

    Input

    第一行一个数字 T (T10),表示测试数据组数

    每组测试数据,第一行两个数 n1n200和 m0m40000,接下来m行,每行两个数ab1a,bN,表示a的名次要先于b

    Output

    对于每组测试数据,输出一行,从1号到n号每个人的名次。

    如果有多个解,让编号为1的人的名次尽量小,然后让编号为2的人的名次尽量小,然后让编号为3的人的名次尽量小......

    如果没有解,输出1

    Sample input and output

    Sample InputSample Output
    5
    4 0
    4 1
    1 1
    4 2
    1 2
    2 1
    4 1
    2 1
    4 1
    3 2
    1 2 3 4
    -1
    -1
    2 1 3 4
    1 3 2 4

    Hint

    注意可能会有重边

    解题思路:

     首先,本题正向拓扑排序是不行的,即如果这样建边:

      U 的名次先于 V , 即 V 向 U连边

    因为题意比较绕,下文都这样叙述:

     排名号越高,其名次越低,第一名的排名号是 1 ,它的名次是最高的.

    我们按照 v 向 u建边,意思是v的排名号高于u.

    无法保证

     让编号为1的人的名次尽量小,然后让编号为2的人的名次尽量小,然后让编号为3的人的名次尽量小.

    è 让编号为 1 的人的排名号尽量大,然后让编号为 2 的人的排名号尽量大….

    我们拓扑排序的顺序是这样的:

     每次寻找入度为 0 的点,将排名号赋给这个点,删边,重复.

    如果有多个点入度都是 0 呢?我们不假思索的这样想:

     我们为了保证题目条件,会使得我们会尽量保证这个点的编号尽量小(这样我们看起来符合了题目条件:编号小的人排名号尽量高),但是我们忽略了,题目要求是先尽力保证编号1的人,之后才是编号2的人….

    所以,正向建边是错误的

    注意,上面的证明非常不严格(Even it's a mistake),如果小伙伴谁有更好的证明,可在下面回复

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <algorithm>
    #include <vector>
    #include <queue>
    #define pb push_back
    using namespace std;
    const int maxn = 200 + 10;
    int n,m,c[maxn],indig[maxn];
    vector<int>E[maxn];
    bool existedge[maxn][maxn];
    int out[maxn];
    
    bool dfs(int cur)
    {
       if (c[cur] == 1)
        return true;
       c[cur] = -1;
       for(int i = 0 ; i < E[cur].size() ; ++ i)
        {
            int nextnode = E[cur][i];
            if (c[nextnode] == -1)
             return false;
            if (!c[nextnode] && !dfs(nextnode)) //exist 环 
             return false;
        }
       c[cur] = 1;
       return true;
    }
    
    
    typedef struct point
    {
      int id,indig;
      friend bool operator < (const point & x,const point & y)
       {
             return x.indig < y.indig;
       }    
      point(int id,int indig)
       {
            this->id = id , this->indig = indig;
       }
    };
    
    
    vector<point>v;
    bool used[maxn];
    
    void ansset()
    {
       memset(used,false,sizeof(used));
       for(int i = 1 ; i <= n ; ++ i)
        v.pb(point(i,indig[i]));
       sort(v.begin(),v.end());
       int rank = 0;
       for(int i = 1 ; i <= n ; ++ i)
        {
           int choose = v[0].id;
           int pos = 0;
           while( pos < v.size() && !v[pos].indig)
            choose = max(choose,v[pos++].id);
           out[choose] =  n - rank++;
           used[choose] = true;
           for(int i = 0 ; i < E[choose].size() ; ++ i)
            indig[E[choose][i]]--;
           v.clear();
           for(int i = 1 ; i <= n ; ++ i)
            if(!used[i])
             v.pb(point(i,indig[i]));
           sort(v.begin(),v.end());
        }
    }
    
    int main(int argc,char *argv[])
    {
      int Case;
      scanf("%d",&Case);
      while(Case--)
       {
             scanf("%d%d",&n,&m);
             memset(c,0,sizeof(c));
             memset(existedge,false,sizeof(existedge));
             memset(indig,0,sizeof(indig));
             while(m--)
              {
                    int u,v;
                    scanf("%d%d",&u,&v);
                    if (existedge[v][u])
                     continue;
                    E[v].pb(u);
                    existedge[v][u] = true;
                    indig[u] ++;
           }
          int ans = 1;
          for(int i = 1 ; i <= n ; ++ i)
           if (!dfs(i))
               {
                  ans = 0;
               break;    
            }
           if (!ans)
            printf("-1
    ");
           else
            {
               v.clear();
               ansset();
               for(int i = 1 ; i <= n ; ++ i)
                i == 1 ? printf("%d",out[i]) : printf(" %d",out[i]);
               printf("
    ");
            }
           for(int i = 1 ; i <= n ; ++ i)
            E[i].clear();
       }
      return 0;
    }
  • 相关阅读:
    webpack4+vue 打包 就是没效果?求解!!!
    Vue.js——6.创建组件
    Vue.js——5.生命周期
    Vue.js——4.指令 笔记
    Vue.js——3.增删改查
    Vue.js——2.第一个Vue程序
    Vue.js——1.初识Vue
    Codeforces 1285D Dr. Evil Underscores
    Codeforces 437B The Child and Set
    ZhongHaoxi P105-3 洗衣
  • 原文地址:https://www.cnblogs.com/Xiper/p/4570664.html
Copyright © 2011-2022 走看看