• CF1070L Odd Federalization 高斯消元


    传送门


    (r = 1)直接判断所有点度数是否为偶数

    考虑(r = 2)的情况。设(x_i=0/1)表示(i)点所在的集合,那么若(2 mid du_u),则(igopluslimits_{(u,v) in e} x_v = 0),否则(igopluslimits_{(u,v) in e} x_v = x_u igoplus 1),即(x_u xor igopluslimits_{(u,v) in e} x_v = 1)

    可以发现上面是一个异或方程组,高斯消元解出来即可。

    但是(r)有可能(> 2)吗?事实上(r)只会等于(1)或者(2)

    可以发现如果(r>2),意味着上面的异或方程组无解。无解则存在某些异或方程能够异或得到(0=1)。右式为(1)意味着有奇数个入度为奇数的点,而左式为(0)意味着所有点在这些异或方程中都出现了偶数次,而度数为奇数的点会在自己的方程中出现一次,所以在这个导出子图中,度数为奇数的点连接了奇数个点,度数为偶数的点连接了偶数个点,这意味着这个导出子图的度数和为奇数。但对于一个无向图度数无论如何都是偶数,所以不存在无解情况,所以(r leq 2)

    #include<bits/stdc++.h>
    using namespace std;
    
    inline int read(){
        int a = 0;
        char c = getchar();
        bool f = 0;
        while(!isdigit(c)){
            if(c == '-')
                f = 1;
            c = getchar();
        }
        while(isdigit(c)){
            a = (a << 3) + (a << 1) + (c ^ '0');
            c = getchar();
        }
        return f ? -a : a;
    }
    
    const int MAXN = 2010;
    bitset < MAXN > gauss[MAXN];
    int N , M , ans[MAXN];
    
    int main(){
        for(int T = read() ; T ; --T){
            N = read();
            M = read();
            for(int i = 1 ; i <= N ; ++i){
                gauss[i].reset();
                gauss[i].set(i);
            }
            for(int i = 1 ; i <= M ; ++i){
                int a = read() , b = read();
                gauss[a][N + 1] = ~gauss[a][N + 1];
                gauss[b][N + 1] = ~gauss[b][N + 1];
                gauss[a][b] = gauss[b][a] = 1;
            }
            bool f = 1;
            for(int i = 1 ; f && i <= N ; ++i)
                f = !gauss[i][N + 1];
            if(f){
                puts("1");
                for(int i = 1 ; i <= N ; ++i)
                    printf("1 ");
            }
            else{
                for(int i = 1 ; i <= N ; ++i)
                    if(!gauss[i][N + 1])
                        gauss[i][i] = 0;
                int now = 1;
                for(int i = 1 ; i <= N ; ++i){
                    int j = now;
                    while(j <= N && !gauss[j][i])
                        ++j;
                    if(j > N){
                        ans[i] = 0;
                        for(int k = 1 ; k < now ; ++k)
                            gauss[k][i] = 0;
                        continue;
                    }
                    if(j != now)
                        swap(gauss[j] , gauss[now]);
                    while(++j <= N)
                        if(gauss[j][i])
                            gauss[j] ^= gauss[now];
                    ++now;
                }
                for(int j = now - 1 ; j ; --j){
                    int p = 0;
                    for(int k = 1 ; !p && k <= N ; ++k)
                        if(gauss[j][k])
                            p = k;
                    ans[p] = gauss[j][N + 1];
                    for(int k = j - 1 ; k ; --k)
                        if(gauss[k][p])
                            gauss[k] ^= gauss[j];
                }
                puts("2");
                for(int i = 1 ; i <= N ; ++i)
                    printf("%d " , ans[i] + 1);
            }
            putchar('
    ');
        }
        return 0;
    }
    
  • 相关阅读:
    ckeditor(在线文本编辑器)使用教程
    一张图轻松搞懂javascript event对象的clientX,offsetX,screenX,pageX区别
    正则表达式
    关于padding与margin的区别
    伪类link,hover,active,visited,focus的区别
    运动框架
    scroll、offset和client的区别
    如何给Sublime安装插件
    获取行间样式与在js中设置样式
    寻找下一个同级元素节点
  • 原文地址:https://www.cnblogs.com/Itst/p/10423837.html
Copyright © 2020-2023  润新知