UOJ Round 19 题解
虽然打得的确一般般,但是不知道为什么有心情来写(
开场……这 T3 怎么这么眼熟?然而数据范围这么大……
写了再说,反正跑不满,说不定卡进去了(
然而不行,5e5 的大样例跑了 0.5s+……
卡了一会感觉布星,溜了。
开始找 T1 的一堆性质,感觉找到了。
然后要找很多极小环,但是不会。
码了个 T2 的暴力就去搞 T1 的极小环了,以为能有 70,最后连那个说大不大的样例都过不去,一画图发现假了。
这时只剩下 10min,改成 20 分暴力走人了。
丢人 20+20+85=125,rk22,居然还能 +78,我也是服。
而且是因为少了一题的区分度,要是 T3 不是原题我就死绝了(
T1
考场思路:
对于 1 操作,如果有两次操作的环有共用边,那么可以等价于一些没有公共边的环。最后肯定可以变成两两没有公共边的一些环。
对于 2 操作,把白点看成 0,黑点看成 1,就是每条边的权值异或上两个端点的权值。所以多次 2 操作可以等价于一次。
也就是说,只要有解(不考虑步数),就一定存在 \(\le\lfloor\frac{m}{3}\rfloor+1\) 步的解。
判断有解,注意到 2 操作中每个点独立,所以可以对于每个点,相邻的边集拿出来。
然后再找出所有极小环。任意的操作都可以等价于某些极小环。
然后高斯消元/线性基就行了。
然而一开始想假了,以为极小环两两没有共用边,然后暴毙了。
70 分做法:
别找极小环了。
随便拎个生成森林,然后每条非树边与树上那条路径的环。
容易发现每个简单环都能等价于某些这种环。(对我没听说过,我孤陋寡闻了 /cy)
那么 \(m\) 个元,bitset 优化即可 \(O(\frac{Tm^3}{w})\)。
满分做法:
考虑只用 1 操作能完成哪些图。
发现就是只考虑 1 边,每个点的度数都是偶数就可以。就是等价于一些简单环在度数大于 2 的地方拼起来(太棒了,学到许多)
那么记录下每个点度数的奇偶性。可以让度数奇偶性变化的,只剩操作 2 了。
操作 2 只有 \(n\) 个方程,元也是 \(n\) 个,复杂度是 \(O(\frac{Tn^3}{w})\)。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
const int maxn=555;
#define MP make_pair
#define PB push_back
#define lson o<<1,l,mid
#define rson o<<1|1,mid+1,r
#define FOR(i,a,b) for(int i=(a);i<=(b);i++)
#define ROF(i,a,b) for(int i=(a);i>=(b);i--)
#define MEM(x,v) memset(x,v,sizeof(x))
inline ll read(){
char ch=getchar();ll x=0,f=0;
while(ch<'0' || ch>'9') f|=ch=='-',ch=getchar();
while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
return f?-x:x;
}
int T,n,m;
bitset<maxn> B,b[maxn],lb[maxn];
void insert(bitset<maxn> b){
ROF(i,n,1) if(b[i]){
if(lb[i]==0){
lb[i]=b;
break;
}
b^=lb[i];
}
}
bool check(bitset<maxn> b){
ROF(i,n,1) if(b[i]) b^=lb[i];
return b==0;
}
int main(){
T=read();
while(T--){
n=read();m=read();
B=0;
FOR(i,1,n) b[i]=lb[i]=0;
while(m--){
int u=read(),v=read(),w=read();
b[u][v]=b[v][u]=1;
if(w) B[u]=B[u]^1,B[v]=B[v]^1;
}
FOR(i,1,n){
if(b[i].count()&1) b[i][i]=1;
insert(b[i]);
}
puts(check(B)?"yes":"no");
}
}
T2(未完成)
考场思路:
什么想法都没有,写了个大暴力。
T3(未完成)
考场思路: