版权声明:随意转载哦......但还是请注明出处吧: https://blog.csdn.net/dreaming__ldx/article/details/86599641
传送门
题意简述:给出一张
,要求删去不超过
条边问最后拓扑序的最大字典序是多少。
思路:贪心帮当前不超过删边上限且权值最大的点删边,用线段树维护一下每个点的入度来支持查询即可。
注意要在选点的时候更新后继的入度
代码:
#include<bits/stdc++.h>
#define ri register int
using namespace std;
inline int read(){
int ans=0;
char ch=getchar();
while(!isdigit(ch))ch=getchar();
while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
return ans;
}
const int N=1e5+5,inf=1e9;
int n,m,k,du[N];
bool vis[N];
vector<int>e[N],ans[N];
namespace SGT{
#define lc (p<<1)
#define rc (p<<1|1)
#define mid (T[p].l+T[p].r>>1)
struct Node{int l,r,mn;}T[N<<2];
inline void pushup(int p){T[p].mn=min(T[lc].mn,T[rc].mn);}
inline void build(int p,int l,int r){
T[p].l=l,T[p].r=r;
if(l==r){T[p].mn=du[l];return;}
build(lc,l,mid),build(rc,mid+1,r),pushup(p);
}
inline void update(int p,int k){
if(T[p].l==T[p].r){T[p].mn=du[T[p].l];return;}
k<=mid?update(lc,k):update(rc,k),pushup(p);
}
inline int query(int p,int k){
if(T[p].l==T[p].r)return T[p].l;
return T[rc].mn<=k?query(rc,k):query(lc,k);
}
}
int main(){
while(~scanf("%d%d%d",&n,&m,&k)){
for(ri i=1;i<=n;++i)e[i].clear(),du[i]=0;
for(ri i=1,u,v;i<=m;++i)u=read(),v=read(),e[u].push_back(v),++du[v];
SGT::build(1,1,n);
for(ri i=1;i<=n;++i){
int x=SGT::query(1,k);
k-=du[x],du[x]=inf,SGT::update(1,x);
for(ri i=0,v;i<e[x].size();++i)if(du[v=e[x][i]]^inf)--du[v],SGT::update(1,v);
if(i==n)cout<<x<<'\n';
else cout<<x<<' ';
}
}
return 0;
}