GDKOI 2021 提高组 Day1 第一题 割(贪心+二分图染色)
GDKOI 2021 提高组 Day1 第一题 割
题目大意
- 给出一种方案使 n n n个点 m m m条边分成两部分,两部分之间的边数 ≥ m 2 \ge\frac{m}{2} ≥2m。
- n ≤ 1 0 5 , m ≤ 2 ∗ 1 0 5 n\le10^5,m\le2*10^5 n≤105,m≤2∗105
题解
- 没用的边删去后,剩下的部分是一张二分图,考虑贪心染色。
- DFS的过程中,每到一个未染色的点,统计与它相邻的点的颜色,将它自己染为较少的那种,令这些点有 s s s个,即边共 s s s条,这样可以保证连出的边 ≥ s 2 \ge\frac{s}{2} ≥2s,那么最后连出的边 ≥ m 2 \ge\frac{m}{2} ≥2m。
代码
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define N 100010
#define M 200010
int last[N], nxt[M * 2], to[M * 2], len = 1;
int co[N], sum = 0;
void add(int x, int y) {
to[++len] = y;
nxt[len] = last[x];
last[x] = len;
}
void dfs(int k) {
int s0 = 0, s1 = 0;
for(int i = last[k]; i; i = nxt[i]) {
s0 += (co[to[i]] == 0), s1 += (co[to[i]] == 1);
}
co[k] = (s1 <= s0);
sum += min(s1, s0);
for(int i = last[k]; i; i = nxt[i]) if(co[to[i]] == -1) dfs(to[i]);
}
int main() {
int n, m, i, x, y;
scanf("%d%d", &n, &m);
for(i = 1; i <= m; i++) {
scanf("%d%d", &x, &y);
add(x, y), add(y, x);
}
memset(co, 255, sizeof(co));
for(i = 1; i <= n; i++) if(co[i] == -1) dfs(i);
for(i = 1; i <= n; i++) printf("%d ", co[i]);
return 0;
}
自我小结
- 其实这题在写的时候本意是贪心骗分,但在写的过程中发下这种做法正确性是保证的。
哈哈哈哈哈哈哈哈哈哈

浙公网安备 33010602011771号