核弹剑仙-【拓扑排序+bitset】

题意

牛牛擅长投影剑类来战斗,他投影的武器甚至有着核弹般的破坏力,故人送外号核弹剑仙。现在牛牛投影了 (n) 把武器,编号为 (1sim n),每把武器都有一个属于自己的破坏力,且任意两把武器之间的破坏力不同。他接下来进行了 (m) 次比较,每次比较会告诉你 (a) 武器破坏力强于 (b) 武器破坏力,数据保证比较结果不会自相矛盾。

请问你能根据这 (m) 次比较结果,告诉牛牛:对于 (i) 号武器,明确比 (i) 号武器破坏力大的武器有多少把吗?

(nleq10^{3},m≤2 imes 10^3)

链接:https://ac.nowcoder.com/acm/contest/6874/F

分析

看到题目,最直接的反应就是拓扑排序。但直接算的话,会出现有一些点重复计算的情况。如:

因此,需要记录每个点的答案的情况。借助 (bitset) 和或的操作,即可避免重复。

代码

#include <bits/stdc++.h>
#define pb push_back
using namespace std;
const int N=1e3+5;
vector<int>pic[N];
int du[N];
queue<int>que;
bitset<1005>bt[N];
void solve(int n)
{
    for(int i=1;i<=n;i++)
    {
        if(du[i]==0)
            que.push(i);
    }
    while(!que.empty())
    {
        int now=que.front();
        que.pop();
        for(int i=0;i<pic[now].size();i++)
        {
            int v=pic[now][i];
            du[v]--;
            bt[v]|=bt[now];
            bt[v].set(now+1);
            if(du[v]==0)
                que.push(v);
        }
    }
}
int main()
{
    int n,m,a,b;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d",&a,&b);
        du[b]++;
        pic[a].pb(b);
    }
    solve(n);
    for(int i=1;i<=n;i++)
        printf("%d
",bt[i].count());
    return 0;
}

原文地址:https://www.cnblogs.com/1024-xzx/p/13549477.html