zoukankan      html  css  js  c++  java
  • SCU

    先上题目:

    4110: PE class

    Submit your solution     Discuss this problem     Best solutions
     

    Description

    The dwarven kingdom and the giant countries classmates have PE class together. 
    The students' height from 1 cm to N cm,everyone's height is different from other's.
    There are N students in total, and there are M pairs of relationship, such as (i, j) 
    said the student's height stand at position i is less than the one stand at position j.
    Can you find each position of the height of students?

    Input

    The first line of input is the number of test case. 
    The first line of each test case contains two integers, N (1 ≤ N ≤ 200) and M (0 ≤ M ≤ 40,000). 
    The next M line each contain two integers a and b, indicating the student's height stand at 
    position a must be less than the one stand at position b. (1 ≤ a, b ≤ N) 
    There is a blank line before each test case.

    Output

    For each test case output one line the students' heights from position 1 to position N. 
    If there are several solutions exist, you should output the one with the smallest height for label 1, 
    then with the smallest height for label 2, then with the smallest height for label 3 and so on... 
    If no solution exists, output one line,just a number -1.
    
    output a blank line after each test case

    Sample Input

    4
    
    4 2
    1 2
    2 1
    
    4 1
    2 1
    
    4 1
    3 2
    
    3 1
    1 1

    Sample Output

    -1
    
    2 1 3 4
    
    1 3 2 4
    
    -1

    Source

    ycg663@scuacm
    Sichuan University Programming Contest 2012 Preliminary

      题意:有身高为1~n的n个人,每个人的身高都不一样,现在要这些人站成一列,给出一系列的关系(i,j)代表i位置的人要比j位置的人矮。现输出字典序最小的拓扑排序结果。

      这一题需要注意的地方是字典序最小,需要逆向构图(有(i,j)的关系,就要构造一条(j,i)的边)。

      为什么需要逆向构图?

      我的理解:字典序最小的逆否命题是除了遵守边的要求以外,还需要注意排在后面的数需要尽量大,所以我们可以在拓扑排序的时候每一次出来一个位置,就给它赋一个还没有用的最大值。

      为什么正向构图就不可以呢?

      先看一组数据

      4 2

      2 3

          4 1

      如果按照正向构图,结果:4 1 2 3

      如果按照逆向构图,结果:1 3 2 4

      我的理解:并不一定所有的点都会被边连在一起,如果点被分成了几组的话,那么这几组的先后顺序就需要考虑了。就像上面的例子一组是2->3,另一组是4->1存在一组里面大位置在小位置前面,同时这个大位置比其他组的开头元素都要大,那就会得出错误的答案了(感觉这里说的还是不是很清楚)。

      感觉这就像需要贪心一样。但是这里在编号的时候因为它给了你限制条件位置编号大的尽量大(当然,这要先符合拓扑排序的要求),所以就需要逆向构图了。

      这一切的根本还是因为拓扑排序结果不唯一。

    上代码:

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <queue>
     5 #define NUM 202
     6 #define MAX 40002
     7 using namespace std;
     8 
     9 int n,m;
    10 
    11 int e[NUM][NUM];
    12 int tot[NUM];
    13 int lo[NUM];
    14 
    15 priority_queue<int,vector<int>,less<int> > p;
    16 bool tp(){
    17     int c=n;
    18     int r=0;
    19     while(!p.empty()) p.pop();
    20     for(int i=1;i<=n;i++) if(tot[i]==0) p.push(i);
    21     while(!p.empty()){
    22         int v=p.top();
    23         lo[v]=c; c--;
    24         r++;
    25         p.pop();
    26         for(int i=1;i<=n;i++){
    27             if(e[v][i]==1){
    28                 tot[i]--;
    29                 if(tot[i]==0){
    30                     p.push(i);
    31                 }
    32             }
    33         }
    34     }
    35     if(r<n) return 0;
    36     return 1;
    37 }
    38 
    39 int main()
    40 {
    41     int t,u,v;
    42     bool f;
    43     //freopen("data.txt","r",stdin);
    44     scanf("%d",&t);
    45     for(int z=0;z<t;z++){
    46         scanf("%d %d",&n,&m);
    47         memset(e,0,sizeof(e));
    48         memset(tot,0,sizeof(tot));
    49         memset(lo,0,sizeof(lo));
    50         f=0;
    51         while(m--){
    52             scanf("%d %d",&u,&v);
    53             if(e[v][u]==0){
    54                 if(u==v) f=1;
    55                 e[v][u]=1;
    56                 tot[u]++;
    57             }
    58         }
    59         if(f || !tp()) printf("-1");
    60         else{
    61             for(int i=1;i<=n;i++){
    62                 if(i!=1) printf(" ");
    63                 printf("%d",lo[i]);
    64             }
    65         }
    66         printf("
    
    ");
    67     }
    68     return 0;
    69 }
    4110
  • 相关阅读:
    辅助随笔:因知识点不足暂时错过的题目
    NOIP2019翻车前写(and 抄)过的代码
    NOIP2019翻车前计划以及日记
    Luogu P3706 [SDOI2017]硬币游戏
    Luogu P5296 [北京省选集训2019]生成树计数
    Luogu P3307 [SDOI2013]项链
    Gaussian整数
    Problem. S
    LOJ6696 复读机 加强版
    数据库约束
  • 原文地址:https://www.cnblogs.com/sineatos/p/3633090.html
Copyright © 2011-2022 走看看