题目链接:
http://7xjob4.com1.z0.glb.clouddn.com/3f644de6844d64706eb36baa3a0c27b0
题目大意:
有n个人m种关系,a->b表示a是b的上级。现在要从中选拔人才,原则是职位越高的人越容易被选拔。给出区间[A,B],现在要算出选A个人时,一定能够被选拔的人数。选B个人时,一定能够被选拔的人数。不管怎么样都不能被选拔的人数(最多选B个人升职)。
思路:
职位越高越容易被选拔,其实就是入度越少越容易被选拔。所以我们做拓扑排序,每次都计算出一批能够有同等机会升职的人数,如此模拟下去,只要人数能够大于等于需要的人数,就可以得到答案了。
代码:
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
int A,B,E,P,tot;
int d[5005],head[5005],vis[5005];
struct node {
int to,next;
}edge[20005];
void add(int a,int b)
{
edge[tot].to=b;
edge[tot].next=head[a];
head[a]=tot++;
}
int main()
{
int i,j,k,a,b,ans[10],x[5005],f1,f2;
queue<int>qu;
while(~(scanf("%d%d%d%d",&A,&B,&E,&P)))
{
f1=f2=0;
while(!qu.empty())qu.pop();
tot=0;
memset(head,-1,sizeof(head));
memset(x,0,sizeof(x));
memset(d,0,sizeof(d));
memset(vis,0,sizeof(vis));
while(P--)
{
scanf("%d%d",&a,&b);
add(a,b);
d[b]++;
}
int t=0;
for(i=0;i<E;i++)
{
if(d[i]==0&&!vis[i]){
vis[i]=1;
qu.push(i);
}
}
while(1)
{
t++;
x[t]=x[t-1]+qu.size();
// printf("1!!!%d\n",x[t]);
if(x[t]>A&&x[t-1]<A&&!f1){ans[1]=min(A,x[t-1]);
if(x[t-1]==0)ans[1]=A;
f1=1;}
if(x[t]==A){ans[1]=x[t];f1=1;}
if(x[t]>B&&x[t-1]<B&&!f2){ans[2]=min(B,x[t-1]);
if(x[t-1]==0)ans[2]=B;
f2=1;}
if(x[t]==B){ans[2]=x[t];f2=1;}
if(f1&&f2)break;
int y=qu.size();
for(i=1;i<=y;i++)
{
int aa=qu.front();
qu.pop();
for(j=head[aa];j!=-1;j=edge[j].next)
{
int as=edge[j].to;
d[as]--;
if(d[as]==0&&!vis[as]){
vis[as]=1;
qu.push(as);
}
}
}
}
printf("%d\n%d\n%d\n",ans[1],ans[2],E-ans[2]);
}
}