ACM/ICPC 之 拓扑排序-反向(POJ3687)

Posted GUARDIAN

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ACM/ICPC 之 拓扑排序-反向(POJ3687)相关的知识,希望对你有一定的参考价值。

难点依旧是题意。。。。需要反向构图+去重+看题

 


 

POJ3687-Labeling Balls

 

  题意:1-N编号的球,输出满足给定约束的按原编号排列的重量序列,如果有多组答案,则输出编号最小的Ball重量最轻,若依旧多组则输出编号次小的Ball重量最轻的方案。

  题解:在看懂题意后,再开始做会省很多时间。。。曲解题意还真是人类的本能啊。

     为了完成单向关系排序,需要用到拓扑排序

     为了符合编号最小的重量最轻...的题意,需要用到反向拓扑排序

     输入可能会有重复的关系,因此需要判重

     输出需要按原编号输出其重量,因此需要在每个编号上标记其重量

 

 1 //给球编号
 2 //1-N编号的球,输出满足给定约束的按原编号排列的重量序列,如果有多组答案,则输出编号越小重量越轻的方案
 3 //反向拓扑+去重+看题...(题意最后需要将Ball的重量按原编号输出)
 4 //迭代器判重:Time:125Ms    Memory:524K
 5 //数组判重:  Time:63Ms    Memory:564K
 6 #include<iostream>
 7 #include<cstring>
 8 #include<cstdio>
 9 #include<vector>
10 using namespace std;
11 
12 #define MAX 205
13 
14 struct Number {
15     vector<int>    light;
16     int in;        //in_degree
17     int weight;    //该编号球的重量
18 }num[MAX];
19 
20 int n, m;
21 bool v[MAX][MAX];
22 
23 bool TopSort()
24 {
25     for (int t = n; t > 0; t--)    //最重到最轻
26     {
27         int cur = n + 1;
28         while (--cur && num[cur].in);    //将最大的label先取出放在最后
29         if (cur == 0) return false;    //有环
30 
31         num[cur].weight = t;    //记录重量
32         num[cur].in--;
33         for (unsigned j = 0; j < num[cur].light.size(); j++)
34             num[num[cur].light[j]].in--;
35     }
36     return true;
37 }
38 
39 int main()
40 {
41     int T;
42     scanf("%d", &T);
43     while (T--)
44     {
45         memset(num, 0, sizeof(num));
46         memset(v, false, sizeof(v));
47         scanf("%d%d", &n, &m);
48         for (int i = 0; i < m; i++)
49         {
50             int light, heavy;
51             scanf("%d%d", &light, &heavy);
52             //反向构图
53             //迭代器判重
54             //vector<int> lg = num[heavy].light;
55             //if (find(lg.begin(), lg.end(), light) != lg.end())    continue;
56             //数组判重
57             if (v[heavy][light]) continue;
58             v[heavy][light] = true;
59             num[heavy].light.push_back(light);
60             num[light].in++;
61         }
62 
63         if (TopSort())
64         {
65             for (int i = 1; i < n; i++)
66                 printf("%d ", num[i].weight);
67             printf("%d\n", num[n].weight);
68         }
69         else printf("-1\n");
70 
71     }
72     
73     return 0;
74 }

 

以上是关于ACM/ICPC 之 拓扑排序-反向(POJ3687)的主要内容,如果未能解决你的问题,请参考以下文章

POJ 3436 ACM Computer Factory 网络流北大ACM/ICPC竞赛训练

ACM/ICPC 之 欧拉回路两道(POJ1300-POJ1386)

ACM/ICPC 之 枚举(POJ1681-画家问题+POJ1166-拨钟问题)

ACM/ICPC 之 经典动规(POJ1088-滑雪)

ACM/ICPC 之 递归(POJ2663-完全覆盖+POJ1057(百练2775)-旧式文件结构图)

ACM/ICPC 之 BFS+状态压缩(POJ1324(ZOJ1361))