首页 > 代码库 > 【vijos】1790 拓扑编号(拓扑+贪心)
【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 << endlinline 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 44 11 35 32 5
样例输出1[复制]
2 3 5 1 4
限制
每个测试点1s
提示
30%的测试点满足:n <= 10, m <= 10
70%的测试点满足:n <= 1000, m <= 10000
100%的测试点满足:n <= 100000, m <= 200000
输入数据可能有重边,可能不连通,但保证是有向无环图。
来源
Topcoder
【vijos】1790 拓扑编号(拓扑+贪心)