题意
一个公司里有E个员工P个上下级关系。这个公司有一种晋升制度。如果要晋升员工a,那么必须要先晋升a的所有领导。给出一个区间[A,B],如果要晋升A个员工,有哪些员工是一定会被晋升的?如果要晋升B个员工,有哪些员工是一定会被晋升的?如果晋升B个员工,有哪些员工是一定不会被晋升的?
分析
这个描述再加上那个样例的图片实在太TM像拓扑排序了啊!当时在场上写了个拓扑排序然后WA的很惨
如果要晋升A个员工,哪些员工是一定会被晋升的?当这个员工的下属数量(包括他自己)大于n-A的时候,则必须晋升它
那么对于每个员工跑dfs统计出它下属的数量就可以。
如果要晋升B个员工,哪些员工是一定不会被晋升的?当这个员工的上司数量大于B的时候,它一定不会被晋升。那么把图反过来,再对每个员工跑一遍dfs就可以,方法和上面一样。
代码如下:
1 #include <cstdio> 2 #include <algorithm> 3 #include <cstring> 4 #include <iostream> 5 #include <vector> 6 #include <queue> 7 using namespace std; 8 const int maxn=5000+10; 9 const int maxm=20000+10; 10 vector<int>G[3][maxn]; 11 int vis[maxn]; 12 int A,B,E,P; 13 int a,b; 14 int ansa,ansb,ansc; 15 int num[maxn]; 16 void dfs(int n,int u,int o){ 17 vis[u]=1; 18 num[o]++; 19 for(int i=0;i<G[n][u].size();i++){ 20 int v=G[n][u][i]; 21 if(!vis[v]) 22 dfs(n,v,o); 23 } 24 return ; 25 } 26 int main(){ 27 ansa=ansb=ansc=0; 28 scanf("%d%d%d%d",&A,&B,&E,&P); 29 memset(num,0,sizeof(num)); 30 for(int i=1;i<=P;i++){ 31 scanf("%d%d",&a,&b); 32 G[1][a].push_back(b); 33 G[2][b].push_back(a); 34 } 35 for(int i=0;i<E;i++){ 36 memset(vis,0,sizeof(vis)); 37 dfs(1,i,i); 38 } 39 for(int i=0;i<E;i++){ 40 if(num[i]>E-A)ansa++; 41 if(num[i]>E-B)ansb++; 42 } 43 memset(num,0,sizeof(num)); 44 for(int i=0;i<E;i++){ 45 memset(vis,0,sizeof(vis)); 46 dfs(2,i,i); 47 } 48 49 for(int i=0;i<E;i++){ 50 if(num[i]>B)ansc++; 51 } 52 cout<<ansa<<endl; 53 cout<<ansb<<endl; 54 cout<<ansc<<endl; 55 return 0; 56 }
另外当时想的拓扑排序为啥是错的呢,当时是觉得跑一遍拓扑排序然后找出每个拓扑顺序上员工的数量,然后由低到高加起来只要现在的数量不超过A。然后这就是一定会被晋升的人数。但是这个晋升关系和拓扑序是有区别的。就拿样例来说,如果要晋升两个员工,按照这种拓扑思想,0和6都是一定会被晋升的,因为他们的拓扑序都是第一个,但题目并不是这个意思,因为晋升了0以后,1也可以得到晋升了,那么晋升两个员工有可能晋升0和6,也可能晋升0和1,所以一定被晋升的只有0结点自己。