易知一个无向图合法的充要条件是每个连通块的点数都是偶数(每次翻转一条路径即可同时改变两个点的度数奇偶性)。
考虑从小到大按边权加入每条边,那么有用的显然只有MST上的边。进一步的,我们发现加入一条边后,原来无用的边显然不会有用。于是可以用LCT维护MST,每次尝试删掉最大边权的边,如果它树上两端的连通块大小均为偶数即可删掉,这个也可以方便地维护。
实现的时候,一开始连上 n − 1 n-1 n−1条边权为 i n f inf inf的边比较方便。时间复杂度 O ( ( n + m ) log n ) \mathcal O((n+m)\log n) O((n+m)logn)。
#include <bits/stdc++.h>
#define inf 0x3f3f3f3f
using namespace std;
struct Edge {
int s,t,v;
Edge() {
}
Edge(int a,int b,int c):s(a),t(b),v(c) {
}
};
Edge e[400005];
bool vis[400005];
int n;
namespace LCT {
int ch[500005][2],fa[500005];
bool rev[500005];
bool size1[500005],size2[500005];
int maxn[500005];
inline void pushdown(int o) {
if (rev[o]) {
if (ch[o][0]) rev[ch[o][0]]^=1;
if (ch[o][1]) rev[ch[o][1]]^=1;
swap(ch[o][0],ch[o][1]);
rev[o]=0;
}
}
inline void pushup(int o) {
int ls=ch[o][0],rs=ch[o][