POJ3687 反向拓扑排序

Labeling Balls

Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 16032   Accepted: 4713

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 bindicating 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

POJ Founder Monthly Contest – 2008.08.31, windy7926778

题意:

给定N个球,编号分别是1-N,重量也是1-N,任意两个球的编号和重量不相等。

给定一些约束:类似编号为a的球比编号为b的球轻,要求输出的答案必须让编号为1的球重量尽量轻,接着是编号为2的球重量尽量轻,一直到编号为N的球尽量轻。

思路:

原命题:编号小的球重量尽量轻。

逆否命题:重量大的球编号尽量大,逆向拓扑排序即可。

PS:数据存在重边,自环等。。

代码:

 1 #include"bits/stdc++.h"
 2
 3 #define db double
 4 #define ll long long
 5 #define vl vector<ll>
 6 #define ci(x) scanf("%d",&x)
 7 #define cd(x) scanf("%lf",&x)
 8 #define cl(x) scanf("%lld",&x)
 9 #define pi(x) printf("%d\n",x)
10 #define pd(x) printf("%f\n",x)
11 #define pl(x) printf("%lld\n",x)
12 #define rep(i, a, n) for (int i=a;i<n;i++)
13 #define per(i, a, n) for (int i=n-1;i>=a;i--)
14 #define fi first
15 #define se second
16 using namespace std;
17 typedef pair<int, int> pii;
18 const int N   = 1e5 + 5;
19 const int mod = 1e9 + 7;
20 const int MOD = 998244353;
21 const db  PI  = acos(-1.0);
22 const db eps  = 1e-10;
23 const int inf = 0x3f3f3f3f;
24 const ll INF  = 0x3fffffffffffffff;
25
26 int n,m,cnt;
27 bool mp[205][205];
28 int du[N],head[N];
29 int a[205];
30 struct P{int to,nxt;}e[N];
31 void add(int u,int v){
32     e[cnt].to=v;
33     e[cnt].nxt=head[u];
34     head[u]=cnt++;
35 }
36 void topsort()
37 {
38     int k=n;
39     priority_queue<int>q;
40     for(int i=1;i<=n;i++) if(!du[i]) q.push(i);
41     while(!q.empty())
42     {
43         int tmp=q.top();
44         q.pop();
45         a[tmp]=k--;
46         for(int i=head[tmp];~i;i=e[i].nxt){
47             int v=e[i].to;
48             du[v]--;
49             if(!du[v]) q.push(v);
50         }
51     }
52     if(k!=0) printf("-1\n");
53     else
54     {
55         for(int i=1;i<=n;i++)
56             printf("%d%c",a[i],i==n?‘\n‘:‘ ‘);
57     }
58 }
59 void init()
60 {
61     memset(mp,0,sizeof(mp));
62     memset(a,0,sizeof(a));
63     memset(head,-1,sizeof(head));
64     memset(du,0,sizeof(du));
65     cnt=0;
66 }
67 int main()
68 {
69     int t;
70     ci(t);
71     while(t--)
72     {
73         init();
74         scanf("%d%d",&n,&m);
75         while(m--)
76         {
77             int x,y;
78             scanf("%d%d",&x,&y);
79             if(mp[x][y]==1) continue;
80             mp[x][y]=1,add(y,x);//反向边
81             du[x]++;
82         }
83         topsort();
84     }
85     return 0;
86 }

原文地址:https://www.cnblogs.com/mj-liylho/p/9556648.html

时间: 2024-11-08 23:51:37

POJ3687 反向拓扑排序的相关文章

HDU 4857 (反向拓扑排序 + 优先队列)

题意:有N个人,M个优先级a,b表示a优先于b,并且每个人有个编号的优先级,输出顺序. 思路来自:与PKU3687一样 在基本的拓扑排序的基础上又增加了一个要求:编号最小的节点要尽量排在前面:在满足上一个条件的基础上,编号第二小的节点要尽量排在前面:在满足前两个条件的基础上,编号第三小的节点要尽量排在前面--依此类推.(注意,这和字典序是两回事,不可以混淆.) 如图 1 所示,满足要求的拓扑序应该是:6 4 1 3 9 2 5 7 8 0. 图 1 一个拓扑排序的例子 一般来说,在一个有向无环图

逃生(HDU4857 + 反向拓扑排序)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4857 题面是中文题面,就不解释题意了,自己点击链接去看下啦~这题排序有两个条件,一个是按给定的那个序列(即输入的u,v,优先级最高),一个是序号从小到大(优先级次之).正向的话由于这两个条件不好维护,所以就想着用反向拓扑排序来实现.首先记录每个节点的出度,然后用优先队列来维护顺序(使用默认的从大到小排序),最后反向输出即可. 代码实现如下: 1 #include <queue> 2 #includ

反向拓扑排序

对于初始没有进行编号,且要求数字小的尽可能在前面 需要进行反向拓扑排序 真的看不懂 反正需要进行 邻接表优化 传送门 传送门 #include <iostream> #include <cstdio> #include <cstring> #include <queue> using namespace std; const int N = 3e4+5; int n,m,cnt; bool mp[N][N]; int du[N],head[N]; int a

Labeling Balls POJ3687 【拓扑排序反向建边】【邻接表】

http://poj.org/problem?id=3687 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: No two balls share the same label. The labeling satisfies several constrains like "The

【HDOJ4857】【反向拓扑排序】

http://acm.hdu.edu.cn/showproblem.php?pid=4857 逃生 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 6665    Accepted Submission(s): 1950 Problem Description 糟糕的事情发生啦,现在大家都忙着逃命.但是逃命的通道很窄,大家只能排成一行.现

正向与反向拓扑排序的区别(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进行比赛,比赛结束后,裁判委员会要将所有参赛队伍从前往后依次排名,但现在裁判委员会不能直接获得每个队的比

HDU 4857 逃生 (反向拓扑排序 &amp; 容器实现)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4857 逃生 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 4505    Accepted Submission(s): 1282 Problem Description 糟糕的事情发生啦,现在大家都忙着逃命.但是逃命的通道很窄,大家只能排

HDU 4857 逃生(反向拓扑排序+优先队列)

( ̄▽ ̄)" //这题对序号输出有要求,较小的序号优先输出,所以用到优先队列 //优先队列是优先弹出值最大的,所以最后要反向输出结果,才是正确的output #include<iostream> #include<cstdio> #include<cmath> #include<algorithm> #include<cstring> #include<string> #include<cstdlib> #inc

hdu 4857 逃生【反向拓扑排序】

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4857 题意:中文不解释 解法: input: 1 3 1 3 1 answer: 3 1 2 而不是 2 3 1 所以逆向建边 拓扑 代码: #include<stdio.h> #include<iostream> #include<math.h> #include<stdlib.h> #include<ctype.h> #include<a