题目

有一个图,每次加入一条边,对于每个加入的边分别输出加入这条边之后,加入的所有边中选择若干条使得所有点的度数为奇数,用到的边最长是多少。


思考历程

比赛时是推出了很多条性质的。
但是一开始就理解错了题意,题目中的“道路”我理解成了路径,实际上是边。
由于经过这种想法改过的题意过于毒瘤,我几乎没有思路。
最终打了暴力上去,居然能水5分。


正解

有条性质:
一个连通块符合条件,当且仅当这个连通块的总点数为偶数。
(这个连通块是只要用的和不用的边都加进去形成的连通块)
首先,通过度数的奇偶性,可以发现把用到的边都加进去之后,最终形成的都是偶数连通块。
考虑在偶数联通块中构造一个合法的方案:建立一棵生成树,随便选一个点作为根,从叶子往上做。首先选择叶子的父亲边,保证叶子的度数为奇数。对于上面的每个点,看看有多少个通向儿子的边被选了,根据它的奇偶性来决定它到父亲的边选不选。
最终只剩下根节点。我们可以通过度数总和来计算出根节点的度数,发现这时候它也是奇数度数的。
这样就证完了。

这条性质是这道题的灵魂,有了它,意味着我们需要选择一些边,使得图分成若干个偶数连通块。这些边可能在最终的答案中不会用到,但没有关系。这时候答案为最长边。
可以这样暴力:直接最小生成树,维护奇数连通块的个数,第一次等于零的时候输出最后加入的那条边。

由此延伸出了无数种做法,比如可以随便LCT撵爆。
讲个线段树分治。
对于一条边,考虑它在那些询问中被选择,容易发现这是一段区间,头是它加入的时候,我们试着计算出尾。
用一个链表从小到大存下所有边,表示没有确定出尾的位置的边有哪些。
线段树分治的时候从后往前做。到叶子节点的时候,如果当前仍然存在奇数区间,那就将链表中的边从头到尾扔进图中,直到不存在奇数区间为止。这些边在这个时候已经确定了它们的尾,所以把他们从并查集中删去,并在它们影响到的区间上打上标记。
进入一个节点时将标记的边加入图中,退出的时候撤销。


代码

using namespace std;
#include <cstdio>
#include <cstring>
#include <cassert>
#include <algorithm>
#define N 100010
#define M 300010
int n,m;
struct edge{int u,v,w;
} ed[M];
int q[M],nxt[M];
bool cmpq(int a,int b){return ed[a].w<ed[b].w;}
struct EDGE{int id;EDGE *las;
} e[M*40];
int ne;
EDGE *last[M*4];
int odd;
int fa[N],siz[N];
int getfa(int x){return fa[x]==x?x:getfa(fa[x]);}
int opt[N],cnt;
void clear(int btm){for (;cnt>btm;--cnt){int u=opt[cnt],v=fa[u];odd=odd-(siz[v]&1)+(siz[u]&1)+(siz[v]-siz[u]&1);siz[v]-=siz[u];fa[u]=u;}
}
int ans[M];
void cover(int k,int l,int r,int st,int en,int x){if (st<=l && r<=en){e[ne]={x,last[k]};last[k]=e+ne++;return;}int mid=l+r>>1;if (st<=mid)cover(k<<1,l,mid,st,en,x);if (mid<en)cover(k<<1|1,mid+1,r,st,en,x);
}
void calc(int k,int mx){int tmp=cnt,x=nxt[0],lst=0;for (;odd && x<=m;lst=x,x=nxt[x]){nxt[0]=nxt[x];if (q[x]>k)continue;if (q[x]<=k-1)cover(1,1,m,q[x],k-1,q[x]);mx=max(mx,ed[q[x]].w);int u=getfa(ed[q[x]].u),v=getfa(ed[q[x]].v);if (u!=v){odd=odd-(siz[u]&1)-(siz[v]&1)+(siz[u]+siz[v]&1);if (siz[u]>siz[v])swap(u,v);fa[u]=v;siz[v]+=siz[u];opt[++cnt]=u;}}if (odd)ans[k]=-1;elseans[k]=mx;clear(tmp);
}
void dfs(int k,int l,int r,int mx){int tmp=cnt;
//  printf("%d %d\n",k,last[k]);for (EDGE *ei=last[k];ei;ei=ei->las){int u=getfa(ed[ei->id].u),v=getfa(ed[ei->id].v);mx=max(mx,ed[ei->id].w);if (u==v)continue;odd=odd-(siz[u]&1)-(siz[v]&1)+(siz[u]+siz[v]&1);if (siz[u]>siz[v])swap(u,v);fa[u]=v;siz[v]+=siz[u];opt[++cnt]=u;}if (l==r){calc(l,mx);clear(tmp);return;}int mid=l+r>>1;dfs(k<<1|1,mid+1,r,mx);dfs(k<<1,l,mid,mx);clear(tmp);
}
int main(){freopen("road.in","r",stdin);freopen("road.out","w",stdout);scanf("%d%d",&n,&m);for (int i=1;i<=m;++i)scanf("%d%d%d",&ed[i].u,&ed[i].v,&ed[i].w),q[i]=i;sort(q+1,q+m+1,cmpq);for (int i=0;i<=m;++i)nxt[i]=i+1;odd=n;for (int i=1;i<=n;++i)fa[i]=i,siz[i]=1;dfs(1,1,m,0);for (int i=1;i<=m;++i)printf("%d\n",ans[i]);return 0;
}

总结

如果比赛时看懂了题意,说不定当时就想出来了呢……

6491. 【GDOI2020模拟03.04】铺路相关推荐

  1. 【392天】跃迁之路——程序员高效学习方法论探索系列(实验阶段149-2018.03.04)...

    @(一只心中无码的程序员)专栏 实验说明 从2017.10.6起,开启这个系列,目标只有一个:通过探索新的学习方法,用2年的时间,实现2.5倍速的成长,获得普通程序员>= 5年的技术水平. 实验 ...

  2. 面试题 03.04. 化栈为队/面试题09. 用两个栈实现队列/232. 用栈实现队列

    2020-05-08 1.题目描述 用两个栈实现一个队列 2.题解 将一个栈用来进行入操作,另一个进行出操作,入栈直接入,出栈的时候如果是空的则把另一个 栈中的所有元素移动过来,再进行出栈,否则直接出 ...

  3. 《SRPG游戏开发》导航(2019.03.04更新)

    <SRPG游戏开发>导航 第一章到第五章并没有使用Markdown,且经过CSDN几次改版和取消目录,这几章排版有些怪怪的. 2019.03.04 第十一章(十 - 十二) ,间章 第十一 ...

  4. JZOJ 6481. 【GDOI2020模拟02.22】黎曼几何(矩阵乘法)

    JZOJ 6481. [GDOI2020模拟02.22]黎曼几何 题解 设fn,1f_{n,1}fn,1​和fn,2f_{n,2}fn,2​分别表示将nnn个硬币移动111格和222格的最小步数, 推 ...

  5. 2017.03.04【NOIP 普及组】模拟赛C组 T4:泽泽在埃及

    **[2011.12.10普及模拟]泽泽在埃及 ** 题目描述 泽泽已52:0的比分输了球,被足球流氓打了一顿,扔进了窨井里-- 出来的时候,泽泽已经在埃及了. 滚滚的黄沙在周围飞舞,没有一样生物在这 ...

  6. java学习笔记④MySql数据库--03/04 DQL查询

    03 使用DQL查询数据(一) 04 使用DQL查询数据(二) DQL 数据查询语言  select select * 方式效率低 AS 取别名 (给字段取别名,给表取别名,给计算结果取别名) as取 ...

  7. 【十四、网站备案、博客备案、工信部备案】2021最详细wordpress博客建站教程(2021.03.04更新)

    通过本wordpress博客建站教程系列系列文章,你可以不懂网页代码条件下,搭建一个谷歌insight测评90分的个人博客,最低费用在每年80块.本人搭建博客小站点击下面链接即可进入:         ...

  8. 【十五、网站公安备案】2021最详细wordpress博客建站教程(2021.03.04更新)

    通过本wordpress博客建站教程系列系列文章,你可以不懂网页代码条件下,搭建一个谷歌insight测评90分的个人博客,最低费用在每年80块.本人搭建博客小站点击下面链接即可进入:         ...

  9. 黑马程序员 一步一步往上爬 学习毕老师java视频的第03,04天

    ---------------------- <a href="http://edu.csdn.net/heima" target="blank"> ...

最新文章

  1. iOS 设置UILabel 的内边距
  2. springmvc整合mybatis框架源码 bootstrap html5 mysql oracle maven SSM
  3. Strongswan — 常用配置说明
  4. 在OpenCV中将cv::Mat绘制到MFC的视图中
  5. 对计算机网络用户而言 掌握网络,计算机网络的特点
  6. php防止cc攻击代码,防cc攻击PHP防CC攻击实现代码
  7. 移动办公计算机,最适合移动办公的三款掌上电脑点评
  8. 蓝湖完成 10 亿元 C+ 轮融资,发布一站式产品设计协作工具
  9. 【Elasticsearch】Elasticsearch 集群协调迎来新时代
  10. php 图片裁剪保存,PHP图片裁剪与缩放示例(无损裁剪图片)
  11. 两独立样本非参数检验的Mann-whitneyU检验
  12. dns劫持解决方法有哪些、dns劫持什么意思
  13. 微信收钱的盒子服务器老是断开,好哒微信、支付宝入账异常处理办法
  14. cdn 配合 oss加速
  15. mysql之数据库引擎
  16. 前端知识的浅薄了解2
  17. 机器学习项目中遇到的难题_现代难题:何时使用规则与机器学习
  18. BI 前端实践 6:自定义模板展示多维分析结果
  19. 人工智能将改变教育的未来:让我们变得更聪明
  20. MySQL系列:java单例模式例子

热门文章

  1. bom更改编号 sap_SAP ERP系统如何通过LSMW批量更改BOM
  2. 《SpringCloud Alibaba 微服务架构》专题(二十一)-Seat简介与安装
  3. 弱监督语义分割-SEC(seed、expand and constrain)的原理详述
  4. STM32的超声波测距程序
  5. 操作系统的特点及其作用
  6. 呃呃呃呃呃呃鹅鹅鹅鹅鹅鹅饿
  7. FTP服务器配置(虚拟用户)
  8. Codeforces Round #702 (Div. 3) C. Sum of Cubes
  9. 亚马逊上传报告报错常见情况
  10. java知识串讲_java基础知识串讲