UOJ513 清扫银河(高斯消元)

Posted sunshine-chen

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了UOJ513 清扫银河(高斯消元)相关的知识,希望对你有一定的参考价值。

 首先转化一波:

对于1操作,我们求原图的生成树,然后对于每条非树边记下它和树边形成的环,这样的操作共有 $m-n+1$ 个;

对于2操作,我们考虑对于 $n$ 个结点,把和这个结点相连的边状态反转。

 不难发现任何操作序列都可以拆成这 $m+1$ 个操作,且显然每个操作最多进行一次,所以只用考虑这 $m+1$ 个操作就可以了。

直接跑异或方程组消元就可以做到 $O(frac{Tm^3}{w})$。

怎么优化呢?手玩一下可以发现:如果和每个点相连的堵塞边条数都是偶数,那么一定有解(证明可以看官方题解反正我也不会证

而1操作是不会改变这个值的奇偶性的,因此只用考虑2操作,复杂度下降为 $O(frac{Tn^3}{w})$。

一个简单的 trick:跑高斯消元的时候把所有全零式子扔到最后,那么判有解/无解只要检查最后的式子即可。

技术图片
#include<cstdio>
#include<algorithm>
#include<bitset>
#define For(i,A,B) for(i=(A);i<=(B);++i)
using namespace std;
const int N=305;
bool s[N];
bitset<N> a[N];
int main(){
    int T,n,m,i,j,u,v,w,p,cur;
    bool ok;
    scanf("%d",&T);
    while(T--){
        scanf("%d%d",&n,&m);
        For(i,1,n)a[i].reset();
        while(m--){
            scanf("%d%d%d",&u,&v,&w);
            a[u].flip(u);a[u].set(v);
            a[v].flip(v);a[v].set(u); 
            if(w){a[u].flip(0);a[v].flip(0);}
        }
        cur=1;
        For(i,1,n){
            For(p,cur,n)if(a[p][i])break;
            if(p>n)continue;
            if(p!=cur)swap(a[cur],a[p]);
            For(j,cur+1,n)if(a[j][i])a[j]^=a[cur];
            ++cur;
        }
        ok=1;
        For(i,cur,n)if(a[i][0]){ok=0;break;}
        puts(ok?"yes":"no");
    }
    return 0;
}
View Code

 

以上是关于UOJ513 清扫银河(高斯消元)的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ3168[Heoi2013]钙铁锌硒维生素 高斯消元求矩阵的逆+匈牙利算法

模板高斯(约旦)消元

高斯消元总结

高斯消元学习

UOJ513 娓呮壂閾舵渤

UOJ #62. UR #5怎样跑得更快