UVALive 7272 Promotions【拓扑排序】【bitset】

来源:互联网 发布:java中的foreach循环 编辑:程序博客网 时间:2024/06/12 13:40

UVALive 7272 Promotions【拓扑排序】【bitset】

题目链接:https://vjudge.net/problem/UVALive-7272

题目大意:给你一个拓扑排序图,即有n个人m个关系,每个关系a->b表示a表现的比b好,即如果选择了b那么就一定要选择a。现在要评优,分别求出选出A个优秀时一定能评上的人数,选出B个优秀时一定能评上的人数,选出B个优秀也评不上的人数。

题目思路:对于所有的人来说,如果他最晚出现的位置还在评优名额内,那么他一定就可以评上;如果最早出现的位置也不在评优名额内,那么一定就评不上。求出一个节点位置的前驱个数,就是他最早出现的位置,求出一个节点的后继个数,n-后继个数就是最晚出现的位置。通过每次比较计数即可。

#include <cstdio>#include <cstring>#include <string>#include <iostream>#include <algorithm>#include <set>#include <vector>#include <bitset>using namespace std;const int maxn = 5009;int A,B,n,m;vector<int> edge[maxn],edge2[maxn];bitset<maxn> pre[maxn],nx[maxn];bool vis[2][maxn];void init(){    int tx,ty;    for(int i=1;i<=n;++i)    {        edge[i].clear();        edge2[i].clear();    }    for(int i=1;i<=m;++i)    {        scanf("%d%d",&tx,&ty);        edge[tx].push_back(ty);//edges[tx]指的是tx指向哪些对象        edge2[ty].push_back(tx);//edges2[ty]指的是ty被哪些对象指向    }    memset(vis,0,sizeof(vis));}void dfs(int u)//往后找{    if (vis[0][u]) return;    vis[0][u]=true;    nx[u].reset();    nx[u][u] = 1;    int sz= edge[u].size();    for(int i=0;i<sz;++i)    {        dfs( edge[u][i] );        nx[u] |= nx[edge[u][i]];    }}void dfs2(int u)//往前找{    if (vis[1][u]) return;    vis[1][u] = true;    pre[u].reset();    pre[u][u]=1;    int sz=edge2[u].size();    for(int i=0;i<sz;++i)    {        dfs2(edge2[u][i]);        pre[u]|=pre[edge2[u][i]];    }}void solve(){    int ans1=0,ans2=0,ans3=0;    for(int i=0;i<n;++i)    {        dfs(i);        dfs2(i);        int cnt=n+1-nx[i].count();        if(cnt<=A) ans1++;        if(cnt<=B) ans2++;        cnt = pre[i].count();        if(cnt>B) ans3++;    }    printf("%d\n%d\n%d\n",ans1,ans2,ans3);}int main(){    while( scanf("%d%d%d%d",&A,&B,&n,&m) == 4 )    {        init();        solve();    }    return 0;}


原创粉丝点击