【POJ2014】RAJ-Rally
作者:互联网
题面
https://www.luogu.org/problem/P3573
题解
拓扑排序神仙题。
因为是$DAG$,所以拓扑排序搞出拓扑序。
在正反两遍$dp$搞出$f[x]$和$g[x]$
再用类似扫描线的方法更新好了。
实现时传承$yyb$的题解,用了可删堆,实现方法和可删除的$AC$自动机一样,也可以用线段树(可能要在线段树上二分跑答案)
#include<queue> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define N 500500 #define ri register int using namespace std; int n,m,ru[N],tup[N],f[N],g[N]; vector<int> to[N],dt[N]; inline int read() { int ret=0,f=0; char ch=getchar(); while (ch<'0' || ch>'9') f|=(ch=='-'),ch=getchar(); while (ch>='0' && ch<='9') ret*=10,ret+=(ch-'0'),ch=getchar(); return f?-ret:ret; } struct keshandui { priority_queue<int> a,b; void push(int x) { a.push(x); } void del(int x) { b.push(x); } int top() { while (!a.empty() && !b.empty() && a.top()==b.top()) a.pop(),b.pop(); return a.top(); } } q; int main(){ n=read(); m=read(); for (ri i=1;i<=m;i++) { int u=read(),v=read(); to[u].push_back(v); dt[v].push_back(u); ru[v]++; } queue<int> Q; for (ri i=1;i<=n;i++) if (!ru[i]) Q.push(i); int cc=0; while (!Q.empty()) { int x=Q.front(); Q.pop(); tup[++cc]=x; for (ri i=0;i<to[x].size();i++) { int y=to[x][i]; ru[y]--; if (!ru[y]) Q.push(y); } } for (ri i=1;i<=n;i++) { int x=tup[i]; for (ri j=0;j<to[x].size();j++) if (f[x]+1>f[to[x][j]]) f[to[x][j]]=f[x]+1; } for (ri i=n;i>=1;i--) { int x=tup[i]; for (ri j=0;j<to[x].size();j++) if (g[to[x][j]]+1>g[x]) g[x]=g[to[x][j]]+1; } for (ri i=1;i<=n;i++) q.push(g[tup[i]]); int ans1=n+1,ans2=-1; for (ri i=1;i<=n;i++) { int x=tup[i]; q.del(g[x]); for (ri j=0;j<dt[x].size();j++) q.del(f[dt[x][j]]+g[x]+1); if (q.top()<ans1) ans1=q.top(),ans2=x; q.push(f[x]); for (ri j=0;j<to[x].size();j++) q.push(f[x]+g[to[x][j]]+1); } printf("%d %d\n",ans2,ans1); }
标签:ch,int,top,RAJ,&&,Rally,POJ2014,include,ri 来源: https://www.cnblogs.com/shxnb666/p/11298468.html