Description:
给出一张DAG表示每个人之间的关系,问选出A/B(A<=B)个人时多少人必须选,选出B个人时多少个人肯定不被选。
Solution:
计算每个点之前最少要选几个点才能选到自己,这样可以算出每个人是否可能被选。再计算可能被选的人中有多少需要自己先选才能被选,统计一下即可。
#include <bits/stdc++.h>
using namespace std;
const int N = 5005;
int n, m, A, B, tot1, tot2;
int vis[N], cnt[N], d[N][N];
vector<int> G[N], rev[N];
int dfs(int u, int s) {
vis[u] = 1;
int ret = 1;
for(int i = 0; i < rev[u].size(); ++i) {
if(!vis[rev[u][i]]) {
d[rev[u][i]][s] = 1;
ret += dfs(rev[u][i], s);
}
}
return ret;
}
int main() {
scanf("%d%d%d%d", &A, &B, &n, &m);
for(int i = 1; i <= m; ++i) {
int u, v;
scanf("%d%d", &u, &v);
++u;
++v;
G[u].push_back(v);
rev[v].push_back(u);
}
int ans1 = 0, ans2 = 0, ans3 = 0;
for(int i = 1; i <= n; ++i) {
memset(vis, 0, sizeof(vis));
cnt[i] = dfs(i, i);
if(cnt[i] <= A) {
++tot1;
}
if(cnt[i] <= B) {
++tot2;
}
if(cnt[i] > B) {
++ans3;
}
}
for(int i = 1; i <= n; ++i) {
int cnt1 = 0, cnt2 = 0;
for(int j = 1; j <= n; ++j) {
if(i != j) {
if(cnt[j] <= A && d[i][j]) {
++cnt1;
}
if(cnt[j] <= B && d[i][j]) {
++cnt2;
}
}
}
if(tot1 - cnt1 <= A && cnt[i] <= A) {
++ans1;
}
if(tot2 - cnt2 <= B && cnt[i] <= B) {
++ans2;
}
}
printf("%d\n%d\n%d\n", ans1, ans2, ans3);
return 0;
}