0
点赞
收藏
分享

微信扫一扫

ZR #1173. 【线上训练 12】图论


题目链接:​​传送门​​(没买的看不了)

很明显这个可以二分,因为要求度数尽量小满足条件的最大的越小越能满足条件
那么就二分一个,看能不能在的限制下将图补成完全图
要把这个图变成完全图的话,条边要加满
度数之和至少为的点才能连边,排一遍序贪心地找两个能凑起度数的点来
如果找不到两个点度数至少为,那么就已经进行不下去了返回
否则就一直加边直到凑够条边
出题人说复杂度是但如果一开始没有边的话复杂度就是
所以我认为的上界是,它过了
出题人没有特意构造数据
正解就是加了一个队列,因为度数之和不超过,所以把堆换成个队列
每次如果新加入的边度数和,就把它们连起来,否则加入队列中
这样减少了一层二分的,复杂度,不知道能不能卡到
的做法:

#include <bits/stdc++.h>
#define
#define
#define
#define

using namespace std;
int n, m, lj[A][A], deg[A], f[A][A]; pi a[A];
bool check(int mid) {
priority_queue<pair<int, pi> > q; int tot = m;
for (int i = 1; i <= n; i++) a[i].fi = deg[i], a[i].se = i;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
f[i][j] = lj[i][j];
while (tot < n * (n - 1) / 2) {
sort(a + 1, a + 1 + n); bool ok = 0;
for (int i = 1; i <= n; i++)
for (int j = 1; j < i; j++)
if (!f[a[i].se][a[j].se] and a[i].fi + a[j].fi >= mid) {
f[a[i].se][a[j].se] = f[a[j].se][a[i].se] = 1;
a[i].fi++, a[j].fi++, tot++, ok = 1;
}
if (!ok) return false;
}
return true;
}

int main(int argc, char const *argv[]) {
cin >> n >> m;
for (int i = 1, u, v; i <= m; i++) {
scanf("%d%d", &u, &v);
lj[u][v] = lj[v][u] = 1;
deg[u]++, deg[v]++;
}
int l = 0, r = 2 * n, ans = 0;
while (l <= r) {
int mid = (l + r) >> 1;
if (check(mid)) ans = mid, l = mid + 1;
else r = mid - 1;
}
cout << ans << endl;
return 0;
}


举报

相关推荐

0 条评论