【vijos】1790 拓扑编号(拓扑+贪心)

https://vijos.org/p/1790

好神的贪心题。。

一开始我也想到了贪心,但是是错的。。sad

就是因为每一个节点的编号与逆图的子树有关,且编号一定是>=子树的儿子+1的。但是想了想很快发现不可做。。因为这种dfs牵扯到的东西太多了。

然后我想到这些约束是不是和差分约束有关,然后就脑补,可是后边发现这也是不可做的,因为差分约束算出来的不是编号。sad。。

无奈看题解。

sad

这个和我第一个想法有关。。。

因为编号一定是>=逆图的子树儿子+1,显然如果每一次将编号从大向小的放是满足这一性质的。

建一个逆的图,那么就是每次取最大的标号度为0的点,那么这个点的编号就是当前剩余的编号。

#include <cstdio>
#include <cstring>
#include <cmath>
#include <string>
#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;
#define rep(i, n) for(int i=0; i<(n); ++i)
#define for1(i,a,n) for(int i=(a);i<=(n);++i)
#define for2(i,a,n) for(int i=(a);i<(n);++i)
#define for3(i,a,n) for(int i=(a);i>=(n);--i)
#define for4(i,a,n) for(int i=(a);i>(n);--i)
#define CC(i,a) memset(i,a,sizeof(i))
#define read(a) a=getint()
#define print(a) printf("%d", a)
#define dbg(x) cout << (#x) << " = " << (x) << endl
#define printarr2(a, b, c) for1(_, 1, b) { for1(__, 1, c) cout << a[_][__]; cout << endl; }
#define printarr1(a, b) for1(_, 1, b) cout << a[_] << ‘\t‘; cout << endl
inline const int getint() { int r=0, k=1; char c=getchar(); for(; c<‘0‘||c>‘9‘; c=getchar()) if(c==‘-‘) k=-1; for(; c>=‘0‘&&c<=‘9‘; c=getchar()) r=r*10+c-‘0‘; return k*r; }
inline const int max(const int &a, const int &b) { return a>b?a:b; }
inline const int min(const int &a, const int &b) { return a<b?a:b; }

priority_queue<int> id;
const int N=100005, M=200005;
int ihead[N], cnt, n, m, tot, in[N], a[N];
struct ED { int to, next; }e[M];
void add(int u, int v) {
	e[++cnt].next=ihead[u]; ihead[u]=cnt; e[cnt].to=v;
}

int main() {
	read(n); read(m); tot=n+1;
	rep(i, m) {
		int u=getint(), v=getint();
		add(v, u); ++in[u];
	}
	for1(i, 1, n) if(in[i]==0) id.push(i);
	while(!id.empty()) {
		int u=id.top(); id.pop();
		a[u]=--tot;
		for(int i=ihead[u]; i; i=e[i].next) {
			--in[e[i].to];
			if(in[e[i].to]==0) id.push(e[i].to);
		}
	}
	for1(i, 1, n) printf("%d ", a[i]);
	return 0;
}

描述

H国有n个城市,城市与城市之间有m条单向道路,满足任何城市不能通过某条路径回到自己。

现在国王想给城市重新编号,令第i个城市的新的编号为a[i],满足所有城市的新的编号都互不相同,并且编号为[1,n]之间的整数。国王认为一个编号方案是优美的当且仅当对于任意的两个城市i,j,如果i能够到达j,那么a[i]应当<a[j]。

优美的编号方案有很多种,国王希望使1号城市的编号尽可能小,在此前提下,使得2号城市的编号尽可能小...依此类推。

格式

输入格式

第一行读入n,m,表示n个城市,m条有向路径。

接下来读入m行,每行两个整数:x,y
表示第x个城市到第y个城市有一条有向路径。

输出格式

输出一行:n个整数
第i个整数表示第i个城市的新编号a[i],输出应保证是一个关于1到n的排列。

样例1

样例输入1[复制]

5 4
4 1
1 3
5 3
2 5

样例输出1[复制]

2 3 5 1 4

限制

每个测试点1s

提示

30%的测试点满足:n <= 10, m <= 10
70%的测试点满足:n <= 1000, m <= 10000
100%的测试点满足:n <= 100000, m <= 200000
输入数据可能有重边,可能不连通,但保证是有向无环图。

来源

Topcoder

时间: 2024-10-13 11:59:11

【vijos】1790 拓扑编号(拓扑+贪心)的相关文章

vijos 拓扑编号

描述 H国有n个城市,城市与城市之间有m条单向道路,满足任何城市不能通过某条路径回到自己. 现在国王想给城市重新编号,令第i个城市的新的编号为a[i],满足所有城市的新的编号都互不相同,并且编号为[1,n]之间的整数.国王认为一个编号方案是优美的当且仅当对于任意的两个城市i,j,如果i能够到达j,那么a[i]应当<a[j]. 优美的编号方案有很多种,国王希望使1号城市的编号尽可能小,在此前提下,使得2号城市的编号尽可能小...依此类推. 格式 输入格式 第一行读入n,m,表示n个城市,m条有向路

拓扑编号 vijos1790

题意就是拓扑排序,要求1的序号尽可能小,然后2的序号尽可能小,3,4... 一开始很容易想到直接贪心,每次选一个入度为0的点,如果有多个,就选编号最小的那个,但是很容易找到反例. 看了下题解,应该是反着做拓扑排序,每次取编号最大的,但是没有人给出证明.下面给出我的证明,欢迎指出错误. ps:参考了一位大牛的文章,poj有一道题类似,参考了他的题解,但是找不到了,所以没法放出他的链接了,先道歉. 假设我们按逆拓扑排序的方法求出了一个拓扑序列(把得到的反序列正过来),记为A. 假设最优解的拓扑序列是

Vijos1790:拓扑编号

描述 H国有n个城市,城市与城市之间有m条单向道路,满足任何城市不能通过某条路径回到自己. 现在国王想给城市重新编号,令第i个城市的新的编号为a[i],满足所有城市的新的编号都互不相同,并且编号为[1,n]之间的整数.国王认为一个编号方案是优美的当且仅当对于任意的两个城市i,j,如果i能够到达j,那么a[i]应当<a[j]. 优美的编号方案有很多种,国王希望使1号城市的编号尽可能小,在此前提下,使得2号城市的编号尽可能小...依此类推. 格式 输入格式 第一行读入n,m,表示n个城市,m条有向路

拓扑编号

#include<cstdio>//https://vijos.org/p/1790 #include<iostream>#include<vector>#include<queue>using namespace std;const int MAXN=500;int n,m;vector<int>map[MAXN];int rudu[MAXN];int b[MAXN][MAXN];int q[MAXN],tail=-1,head=-1;int

【HDU】5195-DZY Loves Topological Sorting(拓扑 + 线段树 + 贪心)

每次找出入度小于K的编号最大点. 找的时候用线段树找,找完之后将这个点出度链接的点的入度全部减一 简直爆炸... #include<cstdio> #include<vector> #include<cstring> #include<algorithm> using namespace std; #define lson (pos<<1) #define rson (pos<<1|1) const int maxn = 100005

图结构练习——推断给定图是否存在合法拓扑序列(拓扑排序推断环)

图结构练习--推断给定图是否存在合法拓扑序列 Time Limit: 1000MS Memory limit: 65536K 题目描写叙述 给定一个有向图,推断该有向图是否存在一个合法的拓扑序列. 输入 输入包括多组.每组格式例如以下. 第一行包括两个整数n,m.分别代表该有向图的顶点数和边数.(n<=10) 后面m行每行两个整数a b.表示从a到b有一条有向边. 输出 若给定有向图存在合法拓扑序列,则输出YES.否则输出NO. 演示样例输入 1 0 2 2 1 2 2 1 演示样例输出 YES

【BZOJ1179】【Apio2009】Atm 强连通分量缩点+拓扑DP/拓扑最长路 kosaraju+tarjan+dfs转非递归三种代码

题解: 首先第一个阶段, 可以写kosaraju.也可以写tarjan. 这两种还都分递归和dfs转非递归. ----------------------------------四种方案. 第二个阶段,可以写拓扑DP 也可以写最长路 ----------------------------------乘上之前的,,八种方案. 本文写了kosaraju递归版,tarjan递归版,kosaraju非递归版. --只怪学校oj系统栈太小..都是逼得啊. 代码1(tarjan): #include <c

codeforces 655D D. Robot Rapping Results Report(拓扑排序+拓扑序记录)

题目链接: D. Robot Rapping Results Report time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standard output While Farmer John rebuilds his farm in an unfamiliar portion of Bovinia, Bessie is out trying some alt

vijos p1471 教主的游乐场(贪心)

传送门:https://vijos.org/p/1471 描述 Orz教主的成员为教主建了一个游乐场,在教主的规划下,游乐场有一排n个弹性无敌的跳跃装置,它们都朝着一个方向,对着一个巨大的湖,当人踩上去装置可以带你去这个方向无限远的地方,享受飞行的乐趣.但是等这批装置投入使用时,却发现来玩的人们更喜欢在这些装置上跳来跳去,并且由于这些装置弹性的优势,不但它们能让人向所对的方向能跳很远,也都能向相反方向跳一定的距离. 于是教主想出了个游戏,这n个装置按朝向相反的方向顺序以1..n编号.第i个装置可