[拓扑排序]PESTC
Posted yuxiaoze
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[拓扑排序]PESTC相关的知识,希望对你有一定的参考价值。
题目描述
PESTC,即 Park of Electronic Science and Technology of China,电子科技公园,更确切地称作沙河
人民公园。每节课下课都会有很多学生从教学楼出来,去下一个教学楼上课,他们和逛公园的人混在一
起,给校园内交通造成一定的拥堵。
整个公园可以抽象成一张由 n 个点 m 条道路形成的有向图,至于为什么是有向的,那是因为逛公园的
人习惯于沿固定的方向游玩。我们都知道,逆着人流走十分危险,很容易发生踩踏事故,但是人们的习
惯难以预测,如果顺着人流走可能会到不了目的地。比如一些大爷大妈喜欢绕着公园走圈,所以跟着大
爷大妈们走的话不一定能到达下次上课的教室。
Kanade 决定用 Harmonics 技能变出一些分身来疏导交通,她希望在 PESTC 里顺着人流走,从任何点
出发,都不会再回到出发点。为了实现这一目标,她需要让某些道路的人流反向走。但是每一条道路至
少要有一定数量的分身指挥交通才能使这条道路的人流反向。因为 Kanade 修改了一些代码,所以现在
只要生成需要反向的道路中需要分身数最多的分身,她们就能自动生成剩余的分身。
Kanade 想知道要达到这样的效果至少要生成多少分身?
输入
从 pestc.in 中读入以下内容:
第一行两个正整数 n,m,表示 PESTC 的点数与道路数;
接下来 m 行,每行三个正整数u,v,w,表示 u到 v有一条有向道路,使这条道路人流反向至少要 w 个
分身。
输出
输出到 pestc.out。
输出一个整数,表示要满足 Kanade 的要求的话至少生成的分身数。
Solution
二分wi,对于每个 wi,对于边权小于等于它的边可以反转也可以不反转,但是大于这个权的一定不
能反转。如果大于这个权的边形成的图无环,那么可以根据拓扑序补充小于等于这个权的边,使得
全图也是无环的。因此,只要大于这个权的边形成的图无环,那么就是一个可行解,从小到大枚举
即可。
1 #include<cstdio> 2 #include<algorithm> 3 #include<queue> 4 #include<cstring> 5 using namespace std; 6 const int N=2e5+5,M=3e5+5; 7 int n,m; 8 int num,last[N],nxt[M],ver[M],w[M],rd[N]; 9 inline void add(int x,int y,int z) 10 {nxt[++num]=last[x]; last[x]=num; ver[num]=y; w[num]=z;} 11 queue<int> q; 12 inline bool check(int mid) 13 {memset(rd,0,sizeof(rd)); 14 for(int i=1;i<=n;i++) 15 for(int j=last[i];j;j=nxt[j]) 16 if(w[j]>mid) rd[ver[j]]++; 17 18 for(int i=1;i<=n;i++) if(!rd[i]) q.push(i); 19 20 while(!q.empty()) 21 {int x=q.front(); q.pop(); 22 23 for(int i=last[x];i;i=nxt[i]) 24 {if(w[i]<=mid) continue; 25 int y=ver[i]; 26 rd[y]--; if(!rd[y]) q.push(y); 27 } 28 } 29 for(int i=1;i<=n;i++) if(rd[i]) return 0; 30 return 1; 31 } 32 int main() 33 { 34 scanf("%d%d",&n,&m); int x,y,z,l=0,r=0,ans=0; 35 36 for(int i=1;i<=m;i++) 37 {scanf("%d%d%d",&x,&y,&z); 38 r=max(r,z); add(x,y,z); 39 } 40 41 while(l<=r) 42 {int mid=l+r>>1; 43 if(check(mid)) ans=mid,r=mid-1; 44 else l=mid+1; 45 } 46 printf("%d",ans); 47 return 0; 48 }
以上是关于[拓扑排序]PESTC的主要内容,如果未能解决你的问题,请参考以下文章