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; }
以上是关于UOJ513 清扫银河(高斯消元)的主要内容,如果未能解决你的问题,请参考以下文章