zoukankan      html  css  js  c++  java
  • Labeling Balls(变种拓扑)

    Labeling Balls

    Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 131072/65536K (Java/Other)
    Total Submission(s) : 20   Accepted Submission(s) : 10
    Problem Description

    Windy has N balls of distinct weights from 1 unit to N units. Now he tries to label them with 1 to N in such a way that:

    1. No two balls share the same label.
    2. The labeling satisfies several constrains like "The ball labeled with a is lighter than the one labeled with b".

    Can you help windy to find a solution?

     
    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 ball labeled with a must be lighter than the one labeled with b. (1 ≤ a, b ≤ N) There is a blank line before each test case.

     
    Output

    For each test case output on a single line the balls' weights from label 1 to label N. If several solutions exist, you should output the one with the smallest weight for label 1, then with the smallest weight for label 2, then with the smallest weight for label 3 and so on... If no solution exists, output -1 instead.

     
    Sample Input
    5

    4 0

    4 1
    1 1

    4 2
    1 2
    2 1

    4 1
    2 1

    4 1
    3 2
     
    Sample Output
    1 2 3 4
    -1
    -1
    2 1 3 4
    1 3 2 4
     
    Source
    PKU
    前言:纠结了好久的一道题目,缘于题目的意思不够明白;
    (PS:一开始以为编号是乱序的,告诉你a编号和b编号的轻重关系,让你求全部编号的轻重的拓扑关系、、、
      其实,编号已经是固定好的从左往右分别是1~N编号)
      1,输入的a,b表示编号a的球比编号b的球轻(j既为a位置的球比b位置的球轻);
      2,输出的是,依次出编号1~N编号的球的重量。(既为位置1~N球的重量,囧囧囧、、、、)
      3,注意输出要求的这一句话:
         “ you should output the one with the smallest weight for label 1, then with the smallest weight for label 2,         then with the smallest weight for label 3 and so on...”,意思既为:编号1的球尽可能的轻,编号2的球尽可能轻...       优先级是从编号小道编号大。也就是说,输出的重量,尽可能的吧重量比较小的放在前面。
      4,如果之间采用正向的拓扑是不可行的,因为正向拓扑的话,既为把这些编号看出是重量,然后从1~N依次获取  (入度为0且字典序最小的点)因为其求出来的是按照字典序的顺序求的,这样求解方式并不是正常的,
        好比如测试样例子:
          5 4
          1 4
          4 2
          5 3
          3 2
        你用正向的拓扑求出来的结果会是:1 4 5 3 2,你会发现 这个样例并没有满足最后一组要求(3 2)=>第三个位置    的球的重量要小于第二个位置球的重量,这样求解出来的结果便是错误的了。
        我看要求的是编号从小到大(1~N)的重量,且希望编号越小的球的重量也越小,也就是说,重量越大的球的     尽量赋给编号比较大的球。按照这个思路,我们这样就可以用反向拓扑来实现(其实就是箭头反向),只需要
        对正向拓扑进行一些修改即可,详细修改点请看代码二:
                  
    题目大意:
     1 #include <stdio.h>
     2 #include <stdlib.h>
     3 #include <string.h>
     4 #define MAXN 205
     5 int InD[205];
     6 int Edge[205][205];
     7 void MakeSet(int Len)
     8 {
     9     int i;
    10     for(i=0;i<=Len;i++)
    11         InD[i]=0;
    12     return;
    13 }
    14 int ToPoSort(int n,int* ret)
    15 {
    16     int i,j,k;
    17     for(j=n;j>=1;j--)
    18     {
    19         for(i=n;i>=1;i--)
    20             if(InD[i]==0)
    21             {
    22                 InD[i]--;
    23                 ret[i]=j;
    24                 for(k=1;k<=n;k++)
    25                     if(Edge[i][k]==1)
    26                         InD[k]--;
    27                 break;
    28             }
    29         if(i<1)break;
    30     }
    31     if(j<=0)
    32         return 1;
    33     else
    34         return 0;
    35 }
    36 
    37 int main()
    38 {
    39     int N,M,i,a,b,ID[205],T;
    40     scanf("%d",&T);
    41     while(T--)
    42     {
    43         scanf("%d%d",&N,&M);
    44         MakeSet(N);
    45         memset(Edge,0,sizeof(Edge));
    46         memset(ID,0,sizeof(ID));
    47         for(i=0;i<M;i++)
    48         {
    49             scanf("%d%d",&a,&b);
    50             if(Edge[b][a]==0)
    51             {
    52                 Edge[b][a]=1;
    53                 InD[a]++;
    54             }
    55         }
    56         if(ToPoSort(N,ID))
    57         {
    58             for(i=1;i<=N;i++)
    59             {
    60                 printf("%d",ID[i]);
    61                 if(i!=N)putchar(32);
    62             }
    63             putchar(10);
    64         }
    65         else
    66             printf("-1
    ");
    67     }
    68     return 0;
    69 }
    View Code

     修改:2015.2.28(邻接表)

      1 #include <iostream>
      2 #include <stdio.h>
      3 #include <string.h>
      4 #include <map>
      5 using namespace std;
      6 #define MAX 215
      7 int InD[MAX];/*InD[i]记录点i的入度*/
      8 int First[MAX];/*First[i]头结点的第一条边的编号*/
      9 struct edge
     10 {
     11     int TO;/**/
     12     int Next;/*下一条边的编号*/
     13 }ID[MAX*MAX];      /*边表,无向图的边数记得多弄些*/
     14 int SIGN; /*链表的边数,链表的边数=无向图边数*2=有向图边数*/
     15 void Add_E(int x,int y)/*添加点+更新入度操作*/
     16 {
     17     ID[SIGN].TO=y;
     18     InD[y]++;
     19     ID[SIGN].Next=First[x];
     20     First[x]=SIGN++;
     21 }
     22 int Jude(int x,int y)/*查找与X是否与Y相连,是0,否1*/
     23 {
     24     int i;
     25     for(i=First[x];i!=0;i=ID[i].Next)   //查找与该点相关的点
     26     {
     27        if(ID[i].TO==y)return 0;
     28     }
     29     return 1;
     30 }
     31 int ToPoSort(int N,int Num[])/*能够排序返回1,否则返回0*/
     32 {/*N为点的个数(1~N),Num[]用来存储排序后的结果*/
     33     int i,j,k;
     34     for(j=N;j>=1;j--)/*修改点一: j作为重量,重量从大到小依次赋值*/
     35     {
     36         for(i=N;i>=1;i--)/*修改点二: i作为编号,编号从大到小查找*/
     37         {
     38             if(InD[i]==0)/*找到符合的编号。进行赋值*/
     39             {
     40                 InD[i]--;
     41                 Num[i]=j;/*修改点三: j作为重量,i作为编号(位置)*/
     42                 for(k=First[i];k!=0;k=ID[k].Next)
     43                 {
     44                     InD[ID[k].TO]--;
     45                 }
     46                 break;
     47             }
     48         }
     49         if(i<1)break;/*如果全部找完,没有找到,退出*/
     50     }
     51     if(j<=0)return 1;/*如果重量能够全部赋值,既可行*/
     52     else return 0;  /*反正不可行。*/
     53 }
     54 int main()
     55 {
     56     int M,N,i,T;
     57     int Num[MAX];
     58     scanf("%d",&T);
     59     while(T--)
     60     {
     61         scanf("%d%d",&N,&M);
     62         int a,b;
     63         for(i=1;i<=N;i++){First[i]=0;InD[i]=0;}
     64         for(i=0,SIGN=1;i<M;i++)
     65         {
     66             scanf("%d%d",&a,&b);
     67             if(Jude(b,a))   /*判断重边*/
     68             {
     69                 Add_E(b,a);
     70             }
     71         }
     72         if(ToPoSort(N,Num))
     73         {
     74             for(i=1;i<=N;i++)
     75             {
     76                 if(i!=1)putchar(32);
     77                 printf("%d",Num[i]);
     78             }putchar(10);
     79         }
     80         else printf("-1
    ");
     81     }
     82     return 0;
     83 }
     84 
     85 /*
     86 4
     87 5 4
     88 1 4
     89 4 2
     90 5 3
     91 3 2
     92 
     93 5 3
     94 1 4
     95 4 2
     96 3 5
     97 
     98 5 4
     99 5 1
    100 4 2
    101 1 3
    102 2 3
    103 
    104 10 5
    105 4 1
    106 8 1
    107 7 8
    108 4 1
    109 2 8
    110 ans:
    111 1 5 3 4 2
    112 1 3 4 2 5
    113 2 4 5 3 1        逆向建图
    114 5 1 6 2 7 8 3 4 9 10  没有判重边的话就输出 -1
    115 
    116 */
    View Code
     
  • 相关阅读:
    【AMAD】django-channels -- 为Django带来异步开发
    【AMAD】django-crispy-forms -- 不要再重复编写Django Form了!
    【AMAD】django-compressor -- 将JS和CSS文件压缩为一个缓存文件
    【AMAD]django-filter -- 一个通用的,基于用户选择的Django Queryset 过滤系统
    【AMAD】django-taggit -- 一个简单的,通用的django tagging模块
    【AMAD】django-debug-toolbar -- 一个可配置的panel,展示当前request/response的debug信息
    【amad】cookiecutter -- 一个命令行工具,使用项目模版来构建项目
    十步学习法 -- 来自<<软技能>>一书的学习方法论
    第八篇、SVN在Mac上使用
    第七篇、Nginx Install On Mac
  • 原文地址:https://www.cnblogs.com/Wurq/p/3929277.html
Copyright © 2011-2022 走看看