Give you a DAG, if you select the U point, you must first select all the points that can reach it. Ask you to choose a point of the case, which points are required, select the B point of the case, which points are required, and select the B point of the case, which points must not be selected.
When you select a point, the required point is the point where the number of points that it can reach is >n-a.
Select the B point, and the required point is similar to the former one.
The point that must not be selected is the point that can reach its points >b.
Deal with a point can reach the number of points, or violence, you can also reverse the side, a bitset to each point to do.
A DAG is still a dag back.
#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;}
Topology Sort "Bitset" gym-101128a-promotions