zoukankan      html  css  js  c++  java
  • 【洛谷3429】[POI2005] DWA-Two Parties(高斯消元)

    点此看题面

    • 给定一张(n)个点(m)条边的无向图,要求把这张图划分为两个点集(可以有一个为空),删去不同点集间的连边。
    • 要求构造一组方案,最大化度数为偶数的点数。
    • (nle200)

    一个奇怪的定理

    奇怪的定理又增加了。。。

    The Gallai Cycle-Cocycle Partition Theorem(证明请自行查阅原论文)告诉我们,一定存在一种点集划分方案,使得所有点度数都是偶数

    所以我们只要考虑怎么构造一组方案就好了。

    高斯消元

    设一个点集中的所有点(x_i=0),另一个点集中(x_i=1)

    判断(i,j)是否在同一点集可以写成(x_ioplus x_joplus1)

    则对于每个点,可以列出一个方程:

    [igoplus_{(i,j)in E}(x_ioplus x_joplus 1)=0 ]

    高斯消元解一下就好了。

    代码:(O(n^3))

    #include<bits/stdc++.h>
    #define Tp template<typename Ty>
    #define Ts template<typename Ty,typename... Ar>
    #define Reg register
    #define RI Reg int
    #define Con const
    #define CI Con int&
    #define I inline
    #define W while
    #define N 200
    using namespace std;
    int n,a[N+5][N+5],v[N+5];I void Gauss()//高斯消元模板
    {
    	RI i,j,k;for(i=1;i<=n;++i)
    	{
    		if(!a[i][i]) {for(j=i+1;j<=n&&!a[j][i];++j);for(k=i;k<=n;++k) swap(a[i][k],a[j][k]);swap(v[i],v[j]);}
    		for(j=i+1;j<=n;++j) if(a[j][i]) for(v[j]^=v[i],k=i;k<=n;++k) a[j][k]^=a[i][k];
    	}
    	for(i=n;i;--i) if(v[i]) for(j=i-1;j;--j) a[j][i]&&(v[j]^=1);
    }
    int main()
    {
    	RI i,x,y;for(scanf("%d",&n),i=1;i<=n;++i) for(scanf("%d",&x);x;--x) scanf("%d",&y),a[i][y]=1,a[i][i]^=1,v[i]^=1;//列方程
    	RI t=0;for(Gauss(),i=1;i<=n;++i) v[i]&&++t;for(printf("%d
    ",t),i=1;i<=n;++i) v[i]&&printf("%d ",i);return 0;//取出x[i]=1的点集
    }
    
    败得义无反顾,弱得一无是处
  • 相关阅读:
    Redis常见七种使用场景(PHP实战)
    session垃圾回收机制
    header 头各种类型文件下载
    SQL优化(面试题)
    spring中bean的生命周期
    JAVA的分布式锁
    Java微服务下的分布式事务介绍及其解决方案
    Java反射
    类加载的三种方式
    Sql语句的基本查询用法,两表联查,3表联查
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/Luogu3429.html
Copyright © 2011-2022 走看看