【拓撲排序】【bitset】Gym - 101128A - Promotions
阿新 • • 發佈:2017-08-07
cnblogs int turn names std amp class ans bitset
給你一張DAG,若選擇u點,則必須先選擇所有能到達其的點。問你在選擇A個點的情況下,哪些點必選;選擇B個點的情況下,哪些點必選;選擇B個點的情況下,哪些點一定不選。
選擇A個點的情況,必選的點是那些其所能到達的點數>n-A的點。
選B個點,必選的點與前者類似。
一定不選的點,是能到達它的點數>B的點。
處理一個點所能到達的點數,要麽暴力,也可以可以將邊反向後,對每個點搞個bitset來做。
一個DAG反向後仍是DAG。
#include<cstdio> #include<bitset> #include<queue> using namespace std; bitset<5010>S[5010]; queue<int>q; int first[5010],e,next[20010],v[20010],siz[5010],si2[5010]; void AddEdge(int U,int V){ v[++e]=V; next[e]=first[U]; first[U]=e; } int firs2[5010],e2,nex2[20010],v2[20010]; void AddEdg2(int U,int V){ v2[++e2]=V; nex2[e2]=firs2[U]; firs2[U]=e2; } int A,B,n,m,du[5010],du2[5010],ans1,ans2,ans3; int main(){ int x,y; // freopen("a.in","r",stdin); scanf("%d%d%d%d",&A,&B,&n,&m); for(int i=1;i<=m;++i){ scanf("%d%d",&x,&y); ++x; ++y; AddEdge(x,y); AddEdg2(y,x); ++du[y]; ++du2[x]; } for(int i=1;i<=n;++i){ S[i].set(i); if(!du2[i]){ q.push(i); } } while(!q.empty()){ int U=q.front(); for(int i=firs2[U];i;i=nex2[i]){ S[v2[i]]|=S[U]; --du2[v2[i]]; if(!du2[v2[i]]){ q.push(v2[i]); } } q.pop(); } for(int i=1;i<=n;++i){ siz[i]=S[i].count(); S[i].reset(); S[i].set(i); if(!du[i]){ q.push(i); } } while(!q.empty()){ int U=q.front(); for(int i=first[U];i;i=next[i]){ S[v[i]]|=S[U]; --du[v[i]]; if(!du[v[i]]){ q.push(v[i]); } } q.pop(); } for(int i=1;i<=n;++i){ si2[i]=S[i].count(); } for(int i=1;i<=n;++i){ if(siz[i]>n-A){ ++ans1; } } for(int i=1;i<=n;++i){ if(siz[i]>n-B){ ++ans2; } } for(int i=1;i<=n;++i){ if(si2[i]>B){ ++ans3; } } printf("%d\n%d\n%d\n",ans1,ans2,ans3); return 0; }
【拓撲排序】【bitset】Gym - 101128A - Promotions