核弹剑仙(拓扑+bitset)

 

知识点bitset+拓扑排序

题目大意:有n把武器,依次编号为1~n,已知m条信息,eg: 武器a比武器b的威力大,

Output:      输出n行,第 i 行表示明确比武器 i 威力大的武器数量

题解

          当a>b,则比a大的武器一定也大于b,所以ans[b]应该加上ans[a]及a本身,但是如果普通的队列+拓扑,ans[b]+=ans[a]+1会出现重复计算的情况,

   样例:3 3         答案:0         ans[1]=0
        1 2              3         ans[2]=ans[3]+1+ans[1]+1=2*(ans[1]+1)+1
        1 3              1         ans[3]=ans[1]+1
        3 2                       //第2行答案应该是2,但是1被重复计算了两遍    

         所以利用bitset来记录,bitset < 1010 > g [ 1010 ] , g [ i ] [ j ] 表示武器 j 比武器 i 的威力大,结果只需要统计g [ i ] 1 的个数即可

         g [ b ] | = g [ a ]     //继承a的状态

         g [ b ] [ a ] = 1       //标记

 

 代码:

#include<stdio.h>
#include<queue>
#include<vector>
#include<bitset>
#include<iostream>
using namespace std;
bitset<1010>g[1010];
queue<int>q;
vector<int>ve[1010];
int in[1010];
void bfs(){
     while(!q.empty()){
        int tem=q.front();q.pop();
        for(int i=0;i<ve[tem].size();i++){
            in[ve[tem][i]]--;
            g[ve[tem][i]]|=g[tem];   //继承
            g[ve[tem][i]][tem]=1;    //记录
            if(in[ve[tem][i]]==0)
                q.push(ve[tem][i]);
        }
     }
}
int main(){
     int n,m,a,b;
     while(~scanf("%d%d",&n,&m)){
        for(int i=1;i<=n;i++){
            g[i].reset();ve[i].clear();     //重置为0
        }
        while(!q.empty())q.pop();
        memset(in,0,sizeof(in));
        for(int i=1;i<=m;i++){
            scanf("%d%d",&a,&b);
            ve[a].push_back(b);
            in[b]++;
        }
        for(int i=1;i<=n;i++)
            if(in[i]==0)q.push(i);
        bfs();
        for(int i=1;i<=n;i++)
            printf("%d\n",g[i].count());
     }
     return 0;
}

 

posted @ 2020-08-27 15:31  十分的月亮  阅读(172)  评论(0编辑  收藏  举报