专栏文章
题解:P10938
P10938题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @miocw7f5
- 此快照首次捕获于
- 2025/12/02 17:08 3 个月前
- 此快照最后确认于
- 2025/12/02 17:08 3 个月前
题目大意
给你一个 DAG,让你求出一个最大的 ,使得这 个点互相都不能到达。
解题思路
首先看到求最大值,就可以想到二分答案,然后这道题就可以转换成判断是否有 个点互相不能到达。
考虑如何进行 Check。
看到 的数据范围就可以尝试用随机化,每次打乱数组顺序,能加入集合就加入集合里面,这样就可以用很简单的方法 AC 了。
Code
CPP#include <bits/stdc++.h>
#define endl '\n'
#define rep(i,j,k) for (auto i = (j); i <= (k); ++i)
#define dwn(i,j,k) for (auto i = (j); i >= (k); --i)
#define repl(i,j,k,w) for (auto i = (j); i <= (k); i += (w))
#define dwnl(i,j,k,w) for (auto i = (j); i >= (k); i -= (w))
#define ll long long
#define ull unsigned long long
using namespace std;
constexpr int N = 291;
array <array <bool, N>, N> dis;
array <int, N> a;
random_device rd;
mt19937 rnd (rd ());
int n, m;
//统计数量
bool _count (int cnt) {
array <int, N> f;
int siz = 0;
rep (i, 1, n) {
rep (j, 1, siz)
if (dis[a[f[j]]][a[i]] or dis[a[i]][a[f[j]]]) //不能加入集合,跳过
goto end;
f[++siz] = i;//加入集合
// cout << a[i] << ' ';
end:;
}
// cout << endl;
if (siz >= cnt) return true;
return false;
}
bool check (int value) {
rep (i, 1, n) a[i] = i;
rep (i, 1, 3500) {
shuffle (a.begin () + 1, a.begin () + n + 1, rnd);//随机打乱顺序
// rep (i, 1, n) cout << a[i] << ' ';
// cout << endl;
// cout << endl;
if (_count (value)) return true;
}
return false;
}
int main (void) {
ios :: sync_with_stdio (false);
cin.tie (nullptr);
cout.tie (nullptr);
cin >> n >> m;
rep (i, 1, m) {
int u, v;
cin >> u >> v;
dis[u][v] = true;
}
// Floyed传递闭包
rep (k, 1, n)
rep (i, 1, n)
rep (j, 1, n)
dis[i][j] |= dis[i][k] and dis[k][j];
int l = 0, r = n, ans = 0;
while (l <= r) {
int mid = l + r >> 1;
// cout << mid << endl;
if (check (mid)) {
ans = mid;
l = mid + 1;
} else r = mid - 1;
}
cout << ans << endl;
return 0;
}
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...