zoukankan      html  css  js  c++  java
  • [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
    ",ans[i]);
    77 }
    View Code
  • 相关阅读:
    源文件声明规则
    JavaBean
    ffmpeg错误:Invalid UE golomb code
    利用android studio 生成 JNI需要的动态库so文件
    Error: Your project contains C++ files but it is not using a supported native build system.
    Andriod studio 目录结构
    ubuntu 16.04扩充root 分区
    错误: H.264 bitstream malformed, no startcode found,
    CIDR
    Qt之QComboBox定制(二)
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/13910275.html
Copyright © 2011-2022 走看看