题目描述:
QAQ…
题目分析:
正着不好做,那么我们建反图,做拓扑时优先输出结束时间大的,尽量为前面的点留下时间
第二问:我们直接在做拓扑的时候不考虑这个点,当队列里的点不符合要求或者没有的时候,即为这个点可以出现的最早值
题目链接:
Ac 代码:
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <queue>
const int maxm=2e6+100;
int head[maxm],net[maxm<<1],to[maxm<<1],deg[maxm],cnt;
int r[maxm],ans[maxm],la[maxm];
int n,m;
inline void addedge(int u,int v)
{
cnt++;
to[cnt]=v,net[cnt]=head[u],head[u]=cnt;
}
struct node{
int t,id;
node(int a,int b):t(a),id(b){}
inline bool operator < (const node&a) const
{
return a.t>t;
}
};
std::priority_queue <node> dl;
inline void topsort()
{
int tot=0;
for(int i=1;i<=n;i++) r[i]=deg[i];
for(int i=1;i<=n;i++) if(!r[i]) dl.push((node){la[i],i});
while(!dl.empty())
{
node now=dl.top();
dl.pop();
ans[++tot]=now.id;
for(int i=head[now.id];i;i=net[i])
if(!(--r[to[i]])) dl.push((node){la[to[i]],to[i]});
}
for(int i=n;i>=1;i--) printf("%d ",ans[i]);
}
inline int Topsort(int x)
{
int tot=0;
while(!dl.empty()) dl.pop();
for(int i=1;i<=n;i++) r[i]=deg[i];
for(int i=1;i<=n;i++) if(!r[i]&&i!=x) dl.push((node){la[i],i});
for(int i=n;i>=1;i--)
{
if(dl.empty()) return i;
node now=dl.top();
dl.pop();
if(now.t<i) return i;
for(int j=head[now.id];j;j=net[j])
if(!(--r[to[j]])&&(to[j]!=x)) dl.push((node){la[to[j]],to[j]});
}
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%d",&la[i]);
for(int i=1;i<=m;i++)
{
int u,v;
scanf("%d%d",&u,&v);
addedge(v,u);
deg[u]++;
}
topsort();
puts("");
for(int i=1;i<=n;i++) printf("%d ",Topsort(i));
return 0;
}