核弹剑仙(拓扑+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; }