[luogu7417]Minimizing Edges P
令$e_{G}(a)$和$o_{G}(a)$分别表示在图$G$中从1到$a$的长度为奇数/偶数的最短路(若该类最短路不存在则为$\infty$),不难得到有以下结论——$f_{G}(a,b)=\begin{cases}[b\ge e_{G}(a)]&(b\equiv 0(mod\ 2))\\ [b\ge o_{G}(a)]&(b\equiv 1(mod\ 2))\end{cases}$
根据这个结论,即要求$\forall a,e_{G}(a)=e_{G'}(a)$且$o_{G}(a)=o_{G'}(a)$
先对原图$G$求出所有$e_{G}(a)$和$o_{G}(a)$,将$a$拆为$a_{0}$和$a_{1}$,并对边$(a,b)$连$(a_{0},b_{1})$和$(a_{1},b_{0})$,最后从$1_{0}$出发bfs即可,时间复杂度为$o(n)$
记$G'$的边集为$E$,那么$\forall a,e_{G}(a)=e_{G'}(a)$且$o_{G}(a)=o_{G'}(a)$当且仅当满足以下两个条件:
1.$(a,b)\in E,|e_{G}(a)-o_{G}(b)|=1$且$|e_{G}(b)-o_{G}(a)|=1$(特别的,定义$|\infty-\infty|=1$)
2.$\forall e_{G}(a)\ne 0,\infty,\exists (a,b)\in E,e_{G}(a)=o_{G}(b)+1$且$\forall o_{G}(a)\ne \infty,\exists (a,b)\in E,o_{G}(a)=e_{G}(b)+1$
(关于这个结论,必要性显然,充分性拆点后对距离从小到大归纳即可)
若存在$a$满足$e_{G}(a)=\infty$,那么根据第1个条件,与其相连的点$o_{G}(b)=\infty$,以此类推,所有点(原图连通)$b$都满足$e_{G}(b)=\infty$或$o_{G}(b)=\infty$($o_{G}(a)=\infty$同理)
此时,对于第2个条件,除1以外(1没有限制)每一个点仅有1维有限制,只需要连向一个可以使其该维满足第2个条件的点,显然这样的点必然存在,最终的边数即为$n-1$
(也即原图没有奇环,不能调整奇偶性,构造方案即取以1为根的最短路径树)
考虑这种情况后,即$\forall a,e_{G}(a),o_{G}(a)\ne \infty$,将其作为点$(\min(e_{G}(a),o_{G}(a)),\max(e_{G}(a),o_{G}(a)))$,并将所有点$(x,y)$按照$x+y$从小到大排序、$x+y$相同时$x$从小到大排序
现在,我们从前往后,依次考虑当前点$(x,y)$,去连边满足其第2个条件
如果之前存在点$(x-1,y+1)$“未完全合法”,显然从中任选一个连边即可,连边后$(x,y)$也成为一个“未完全合法”的点(还需要与$(x\pm 1,y-1)$连边),暂不处理
否则,如果之前存在点$(x-1,y-1)$,直接连边即可,即满足条件
否则,再找到$(x-1,y+1)$连边(若$x=0$时不需要连,否则必然存在),并作为“未完全合法”的点
另外,若$y=x+1$且$(x,y)$作为“未完全合法”的点,注意到$(x+1,y-1)$实际上是$(x,y)$自己,因此若之间存在点$(x,y)$“未完全合法”,将这两点连边即可(并取消两点“未完全合法”的标记)
最终,对于剩下的“未完全合法”的点$(x,y)$,找到$(x\pm 1,y-1)$连边即可,由于必然存在,即边数加上“未完全合法”的点数量即可
(当然这个数量也可以在修改过程中顺便加上)
由此,用map维护$(x,y)$上“未完全合法”的点数量即可支持此过程,时间复杂度为$o(n\log n)$
(关于这一做法的正确性,即是一个贪心,比较显然)

1 #include<bits/stdc++.h>
2 using namespace std;
3 #define N 200005
4 struct Edge{
5 int nex,to;
6 }edge[N<<2];
7 queue<int>q;
8 vector<pair<int,int> >v;
9 map<int,int>mat_vis[N],mat[N];
10 int E,t,n,m,x,y,ans,head[N],vis[N],d[N];
11 void add(int x,int y){
12 edge[E].nex=head[x];
13 edge[E].to=y;
14 head[x]=E++;
15 }
16 void bfs(){
17 d[1]=0;
18 q.push(1);
19 vis[1]=1;
20 while (!q.empty()){
21 int k=q.front();
22 q.pop();
23 for(int i=head[k];i!=-1;i=edge[i].nex)
24 if (!vis[edge[i].to]){
25 d[edge[i].to]=d[k]+1;
26 q.push(edge[i].to);
27 vis[edge[i].to]=1;
28 }
29 }
30 }
31 int main(){
32 scanf("%d",&t);
33 while (t--){
34 scanf("%d%d",&n,&m);
35 E=ans=0;
36 for(int i=0;i<=(n<<1);i++){
37 head[i]=d[i]=-1;
38 vis[i]=0;
39 mat_vis[i].clear(),mat[i].clear();
40 }
41 for(int i=1;i<=m;i++){
42 scanf("%d%d",&x,&y);
43 add(x,y+n);
44 add(y+n,x);
45 add(x+n,y);
46 add(y,x+n);
47 }
48 bfs();
49 if (d[n+1]<0){
50 printf("%d\n",n-1);
51 continue;
52 }
53 v.clear();
54 for(int i=1;i<=n;i++)v.push_back(make_pair(min(d[i],d[i+n]),max(d[i],d[i+n])));
55 sort(v.begin(),v.end());
56 for(int i=0;i<n;i++)mat_vis[v[i].first][v[i].second]=1;
57 for(int i=0;i<n;i++){
58 x=v[i].first,y=v[i].second;
59 if ((x)&&(mat[x-1][y+1])){
60 mat[x-1][y+1]--;
61 mat[x][y]++;
62 ans++;
63 }
64 else{
65 if ((x)&&(mat_vis[x-1][y-1]))ans++;
66 else{
67 mat[x][y]++;
68 ans+=1+(x>0);
69 }
70 }
71 if ((y==x+1)&&(mat[x][y]>=2)){
72 mat[x][y]-=2;
73 ans--;
74 }
75 }
76 printf("%d\n",ans);
77 }
78 }
[luogu7417]Minimizing Edges P的更多相关文章
- 读书笔记-《Training Products of Experts by Minimizing Contrastive Divergence》
Training Products of Experts by Minimizing Contrastive Divergence(以下简称 PoE)是 DBN 和深度学习理论的 肇始之篇,最近在爬梳 ...
- 【OpenMesh】Some basic operations: Flipping and collapsing edges
这一节中你将学到一些OpenMesh中早已提供的基础操作. 内容包括三角形网格边的翻转以及通过连接邻接的顶点边缘折叠. 三角形网格的翻转(Flipping edges) 考虑到两个邻接面的三角形网格中 ...
- R 网络图 nodes,edges属性计算
前面提到了用R画网络图,免不了要对网络图nodes和edges的特征做一些统计.分享下我的代码: ########## nodes edges的统计########### # ####nodes的度有 ...
- Google SketchUp Cookbook: (Chapter 3) Intersection Edges: Cutting and Trimming
软件环境 SketchUp Pro 2018 参考书籍 Google SketchUp Cookbook Trimming an Object 使用 Intersect with Model 裁剪物体 ...
- CF962F Simple Cycles Edges
CF962F Simple Cycles Edges 给定一个连通无向图,求有多少条边仅被包含在一个简单环内并输出 \(n,\ m\leq10^5\) tarjan 首先,一个连通块是一个环,当且仅当 ...
- atcoder NIKKEI Programming Contest 2019 E - Weights on Vertices and Edges
题目链接:Weights on Vertices and Edges 题目大意:有一个\(n\)个点\(m\)条边的无向图,点有点权,边有边权,问至少删去多少条边使得对于剩下的每一条边,它所在的联通块 ...
- Maya cmds filterExpand 列出 选择的 uvs vertices faces edges 等 component 类型
Maya cmds filterExpand 列出 选择的 uvs vertices faces edges 等 component 类型 cmds.ls() 的 flags 中没有指明 uvs 等这 ...
- Maya cmds pymel 快速选择hard edges(硬边)
Maya cmds pymel 快速选择hard edges(硬边) import maya.cmds as cmds cmds.polySelectConstraint(m = 3, t = 0x8 ...
- Codeforces 160D Edges in MST tarjan找桥
Edges in MST 在用克鲁斯卡尔求MST的时候, 每个权值的边分为一类, 然后将每类的图建出来, 那些桥就是必须有的, 不是桥就不是必须有. #include<bits/stdc++.h ...
随机推荐
- JavaFx 监听剪切板实现(Kotlin)
原文地址: JavaFx 监听剪切板实现(Kotlin) | Stars-One的杂货小窝 软件有个需求,想要实现监听剪切板的内容,若内容符合预期,则进行相关的操作,就可以免去用户手动粘贴的操作,提供 ...
- 学习使用Wpf开源的文本编辑器—smithhtmleditor
前言 本文主要介绍使用Wpf文本编辑器--smithhtmleditor. 编辑器使用 首先新建一个项目WpfEditor. 然后到Codeplex下载smithhtmleditor. 下载地址:ht ...
- 题解「BZOJ4310」跳蚤
题目传送门 Description 现在有一个长度为 \(n\) 的字符串,将其划分为 \(k\) 段,使得这 \(k\) 段每一段的字典序最大子串中字典序最大的字符串字典序尽量小.求出这个字符串. ...
- 洛谷4234最小差值生成树 (LCT维护生成树)
这也是一道LCT维护生成树的题. 那么我们还是按照套路,先对边进行排序,然后顺次加入. 不过和别的题有所不同的是: 在本题中,我们需要保证LCT中正好有\(n-1\)条边的时候,才能更新\(ans\) ...
- springcloud整合config组件
config组件 config组件支持两种配置文件获取方式springcould搭建的微服务的配置文件的获取方式有两种.它支持配置服务放在配置服务的内存中(即本地),也支持放在远程Git仓库中或者本地 ...
- 流量治理神器-Sentinel的限流模式,选单机还是集群?
大家好,架构摆渡人.这是我的第5篇原创文章,还请多多支持. 上篇文章给大家推荐了一些限流的框架,如果说硬要我推荐一款,我会推荐Sentinel,Sentinel的限流模式分为两种,分别是单机模式和集群 ...
- [JUC-5]ConcurrentHashMap源码分析JDK8
在学习之前,最好先了解下如下知识: 1.ReentrantLock的实现和原理. 2.Synchronized的实现和原理. 3.硬件对并发支持的CAS操作及JVM中Unsafe对CAS的实现. 4. ...
- Golang通脉之数据类型
标识符与关键字 在了解数据类型之前,先了解一下go的标识符和关键字 标识符 在编程语言中标识符就是定义的具有某种意义的词,比如变量名.常量名.函数名等等. Go语言中标识符允许由字母数字和_(下划线) ...
- nexus设置npm下载管理
nexus设置npm下载管理 第一步 登录私服网页 第二步 创建存储空间(如果使用默认的存储空间,此步骤可省略) 第三步 输入空间的名称,点击create创建 第四步 创建仓库 npm的仓库有三种: ...
- from athletelist import AthleteList出现红色下滑波浪线警告
问题:from athletelist import AthleteList出现红色下滑波浪线警告 经过个人网上搜索了解,这个问题是因为python找不到相关的.py文件,无法导入athletelis ...