您的位置:首页 > 其它

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

2017-10-05 20:09 417 查看
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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: