[cf603E]Pastoral Oddities
一张图合法当且仅当每一个连通块大小都为偶数
必要性:对于一个奇数个的连通块,若每一个点度数都为奇数,那么度数和也为奇数,而每一条边带来的度都为2,因此度数和应该为偶数,矛盾
充分性:一个偶数个点的连通块,必然存在一棵生成树,按照以下方式从底往上,通过每一个点到其父亲的边来控制度数为奇数,由于总度数和为偶数,因此根的度数必然为奇数,即符合条件
对于一个询问,可以直接二分答案并插入小于等于其的边,通过并查集维护连通块奇偶性来判断是否合法
对于多个询问,考虑整体二分,对于当前答案区间$[x,y]$,由于答案是单调递减的(-1视为$\infty$),因此所对应的必然为连续区间$[l,r]$(在这之前我们已经插入了$[1,l]$中边权在$[1,x]$中的边)
对于答案mid,再将其划分为两部分,答案大于mid当且仅当插入在其之前且边权在$[1,mid]$中的边不合法,首先要插入$l$之前边权在$(x,mid]$的边,再枚举断点的位置并插入$[1,mid]$中的边直至合法
分两类讨论,若初始合法,那么区间$[l,r]$的答案都为$x$,否则断点必然为第一个答案小于等于mid的位置,从其划分即可
(特别的,初始若第1条边边权最小,需要将第1条边加入)
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 300005 4 struct ji{ 5 int x,y,z; 6 }e[N],ee[N]; 7 int n,m,tot,st[N],f[N],sz[N],ans[N]; 8 bool cmp(ji x,ji y){ 9 return e[x.z].z<e[y.z].z; 10 } 11 int find(int k){ 12 if (k==f[k])return k; 13 return find(f[k]); 14 } 15 void merge(int x,int y){ 16 x=find(x),y=find(y); 17 if (x!=y){ 18 if (sz[x]<sz[y])swap(x,y); 19 tot-=(sz[x]&1)+(sz[y]&1)-((sz[x]+sz[y])&1); 20 f[y]=x; 21 sz[x]+=sz[y]; 22 st[++st[0]]=y; 23 } 24 } 25 void clear(){ 26 int y=st[st[0]--],x=f[y]; 27 f[y]=y; 28 sz[x]-=sz[y]; 29 tot+=(sz[x]&1)+(sz[y]&1)-((sz[x]+sz[y])&1); 30 } 31 void dfs(int l,int r,int x,int y){ 32 if (l>r)return; 33 if (x==y){ 34 for(int i=l;i<=r;i++) 35 if (x==m)ans[i]=-1; 36 else ans[i]=e[ee[x].z].z; 37 return; 38 } 39 int s=(x+y>>1),now=st[0],mid; 40 for(int i=x+1;i<=s;i++) 41 if (ee[i].z<=l)merge(ee[i].x,ee[i].y); 42 if (!tot)mid=l; 43 else 44 for(mid=l+1;(tot)&&(mid<=r);mid++) 45 if (e[mid].z<=e[ee[s].z].z){ 46 merge(e[mid].x,e[mid].y); 47 if (!tot)break; 48 } 49 while (st[0]>now)clear(); 50 for(int i=x+1;i<=s+1;i++) 51 if (ee[i].z<=l)merge(ee[i].x,ee[i].y); 52 dfs(l,mid-1,s+1,y); 53 while (st[0]>now)clear(); 54 for(int i=l+1;i<=mid;i++) 55 if (e[i].z<=e[ee[x].z].z)merge(e[i].x,e[i].y); 56 dfs(mid,r,x,s); 57 while (st[0]>now)clear(); 58 } 59 int main(){ 60 scanf("%d%d",&n,&m); 61 for(int i=1;i<=m;i++){ 62 scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].z); 63 ee[i]=e[i]; 64 ee[i].z=i; 65 } 66 e[++m]=ji{1,1,0x3f3f3f3f}; 67 ee[m]=ji{1,1,m}; 68 sort(ee+1,ee+m+1,cmp); 69 tot=n; 70 for(int i=1;i<=n;i++){ 71 f[i]=i; 72 sz[i]=1; 73 } 74 if (ee[1].z==1)merge(e[1].x,e[1].y); 75 dfs(1,m-1,1,m); 76 for(int i=1;i<m;i++)printf("%d\n",ans[i]); 77 }