核彈劍仙-【拓撲排序+bitset】
阿新 • • 發佈:2020-08-23
題意
牛牛擅長投影劍類來戰鬥,他投影的武器甚至有著核彈般的破壞力,故人送外號核彈劍仙。現在牛牛投影了 \(n\) 把武器,編號為 \(1\sim n\),每把武器都有一個屬於自己的破壞力,且任意兩把武器之間的破壞力不同。他接下來進行了 \(m\) 次比較,每次比較會告訴你 \(a\) 武器破壞力強於 \(b\) 武器破壞力,資料保證比較結果不會自相矛盾。
請問你能根據這 \(m\) 次比較結果,告訴牛牛:對於 \(i\) 號武器,明確比 \(i\) 號武器破壞力大的武器有多少把嗎?
\(n\leq10^{3},m≤2 \times 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\n",bt[i].count()); return 0; }