P2853 Cow Picnic S(Tarjan 转 DAG,DAG 上 DP)

直接瞪眼,应当先 Tarjan 缩点转 DAG。
然后呢?每个点一个 bitset 暴力转移?
好,就这样。

#include<bits/stdc++.h>
#define pb push_back
using namespace std;
const int K=109,N=1009,M=10009;
vector<int> graph[N],Graph[N];
int k,n,m,cow[K],l[M],r[M];

int dfnt,sccnt,color[N],dfn[N],low[N],siz[N],tmp;
bool vis[N]; stack<int> st;
void dfs(int u){
    vis[u]=1,st.push(u),dfn[u]=low[u]=++dfnt;
    for(int v:graph[u]) if(!dfn[v]) dfs(v),low[u]=min(low[u],low[v]);
    else if(vis[v]) low[u]=min(low[u],dfn[v]);
    if(low[u]!=dfn[u]) return; 
    ++sccnt; do tmp=st.top(),st.pop(),vis[tmp]=0,color[tmp]=sccnt,++siz[sccnt]; while(tmp!=u);
}

bitset<K> dp[N];
int cnt[N],ans; queue<int> q;
int main(){
    scanf("%d%d%d",&k,&n,&m);
    for(int i=1;i<=k;i++) scanf("%d",&cow[i]);
    for(int i=1;i<=m;i++) scanf("%d%d",&l[i],&r[i]),graph[l[i]].pb(r[i]);
    for(int i=1;i<=n;i++) if(!dfn[i]) dfs(i);
    for(int i=1;i<=m;i++) if(color[l[i]]!=color[r[i]])
        Graph[color[l[i]]].pb(color[r[i]]),cnt[color[r[i]]]++;
    for(int i=1;i<=k;i++) dp[color[cow[i]]][i]=1;
    for(int i=1;i<=sccnt;i++) if(cnt[i]==0) q.push(i);
    while(!q.empty()){
        tmp=q.front(),q.pop();
        for(int v:Graph[tmp]){
            dp[v]|=dp[tmp];
            if(--cnt[v]==0) q.push(v);
        }
    }
    for(int i=1;i<=sccnt;i++) if(dp[i].count()==k) ans+=siz[i];
    printf("%d\n",ans);
    return 0;
}

其实正解是每个点跑 BFS。

posted @ 2026-02-22 22:28  2025ing  阅读(0)  评论(0)    收藏  举报