zoukankan      html  css  js  c++  java
  • GDKOI 2021 提高组 Day1 第一题 割(贪心+二分图染色)

    GDKOI 2021 提高组 Day1 第一题 割

    题目大意

    • 给出一种方案使 n n n个点 m m m条边分成两部分,两部分之间的边数 ≥ m 2 gefrac{m}{2} 2m
    • n ≤ 1 0 5 , m ≤ 2 ∗ 1 0 5 nle10^5,mle2*10^5 n105,m2105

    题解

    • 没用的边删去后,剩下的部分是一张二分图,考虑贪心染色。
    • DFS的过程中,每到一个未染色的点,统计与它相邻的点的颜色,将它自己染为较少的那种,令这些点有 s s s个,即边共 s s s条,这样可以保证连出的边 ≥ s 2 gefrac{s}{2} 2s,那么最后连出的边 ≥ m 2 gefrac{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;
    }
    

    自我小结

    • 其实这题在写的时候本意是贪心骗分,但在写的过程中发下这种做法正确性是保证的。
    哈哈哈哈哈哈哈哈哈哈
  • 相关阅读:
    HDU4411 最小费用流
    HDU5934 强连通分量
    一个问题
    SAP模板
    KMP模板
    ]C#中执行SQL文件脚本的代码(非常有用)
    C#调用非托管程序5种方式
    [转]C#中的静态常量(const)和动态常量(static和readonly)用法和区别
    [转]C#开发命名规范总结整理
    [转]关于同步方法里面调用异步方法的探究
  • 原文地址:https://www.cnblogs.com/LZA119/p/14437606.html
Copyright © 2011-2022 走看看