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。

浙公网安备 33010602011771号