令$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的更多相关文章

  1. 读书笔记-《Training Products of Experts by Minimizing Contrastive Divergence》

    Training Products of Experts by Minimizing Contrastive Divergence(以下简称 PoE)是 DBN 和深度学习理论的 肇始之篇,最近在爬梳 ...

  2. 【OpenMesh】Some basic operations: Flipping and collapsing edges

    这一节中你将学到一些OpenMesh中早已提供的基础操作. 内容包括三角形网格边的翻转以及通过连接邻接的顶点边缘折叠. 三角形网格的翻转(Flipping edges) 考虑到两个邻接面的三角形网格中 ...

  3. R 网络图 nodes,edges属性计算

    前面提到了用R画网络图,免不了要对网络图nodes和edges的特征做一些统计.分享下我的代码: ########## nodes edges的统计########### # ####nodes的度有 ...

  4. Google SketchUp Cookbook: (Chapter 3) Intersection Edges: Cutting and Trimming

    软件环境 SketchUp Pro 2018 参考书籍 Google SketchUp Cookbook Trimming an Object 使用 Intersect with Model 裁剪物体 ...

  5. CF962F Simple Cycles Edges

    CF962F Simple Cycles Edges 给定一个连通无向图,求有多少条边仅被包含在一个简单环内并输出 \(n,\ m\leq10^5\) tarjan 首先,一个连通块是一个环,当且仅当 ...

  6. atcoder NIKKEI Programming Contest 2019 E - Weights on Vertices and Edges

    题目链接:Weights on Vertices and Edges 题目大意:有一个\(n\)个点\(m\)条边的无向图,点有点权,边有边权,问至少删去多少条边使得对于剩下的每一条边,它所在的联通块 ...

  7. Maya cmds filterExpand 列出 选择的 uvs vertices faces edges 等 component 类型

    Maya cmds filterExpand 列出 选择的 uvs vertices faces edges 等 component 类型 cmds.ls() 的 flags 中没有指明 uvs 等这 ...

  8. Maya cmds pymel 快速选择hard edges(硬边)

    Maya cmds pymel 快速选择hard edges(硬边) import maya.cmds as cmds cmds.polySelectConstraint(m = 3, t = 0x8 ...

  9. Codeforces 160D Edges in MST tarjan找桥

    Edges in MST 在用克鲁斯卡尔求MST的时候, 每个权值的边分为一类, 然后将每类的图建出来, 那些桥就是必须有的, 不是桥就不是必须有. #include<bits/stdc++.h ...

随机推荐

  1. JavaFx 监听剪切板实现(Kotlin)

    原文地址: JavaFx 监听剪切板实现(Kotlin) | Stars-One的杂货小窝 软件有个需求,想要实现监听剪切板的内容,若内容符合预期,则进行相关的操作,就可以免去用户手动粘贴的操作,提供 ...

  2. 学习使用Wpf开源的文本编辑器—smithhtmleditor

    前言 本文主要介绍使用Wpf文本编辑器--smithhtmleditor. 编辑器使用 首先新建一个项目WpfEditor. 然后到Codeplex下载smithhtmleditor. 下载地址:ht ...

  3. 题解「BZOJ4310」跳蚤

    题目传送门 Description 现在有一个长度为 \(n\) 的字符串,将其划分为 \(k\) 段,使得这 \(k\) 段每一段的字典序最大子串中字典序最大的字符串字典序尽量小.求出这个字符串. ...

  4. 洛谷4234最小差值生成树 (LCT维护生成树)

    这也是一道LCT维护生成树的题. 那么我们还是按照套路,先对边进行排序,然后顺次加入. 不过和别的题有所不同的是: 在本题中,我们需要保证LCT中正好有\(n-1\)条边的时候,才能更新\(ans\) ...

  5. springcloud整合config组件

    config组件 config组件支持两种配置文件获取方式springcould搭建的微服务的配置文件的获取方式有两种.它支持配置服务放在配置服务的内存中(即本地),也支持放在远程Git仓库中或者本地 ...

  6. 流量治理神器-Sentinel的限流模式,选单机还是集群?

    大家好,架构摆渡人.这是我的第5篇原创文章,还请多多支持. 上篇文章给大家推荐了一些限流的框架,如果说硬要我推荐一款,我会推荐Sentinel,Sentinel的限流模式分为两种,分别是单机模式和集群 ...

  7. [JUC-5]ConcurrentHashMap源码分析JDK8

    在学习之前,最好先了解下如下知识: 1.ReentrantLock的实现和原理. 2.Synchronized的实现和原理. 3.硬件对并发支持的CAS操作及JVM中Unsafe对CAS的实现. 4. ...

  8. Golang通脉之数据类型

    标识符与关键字 在了解数据类型之前,先了解一下go的标识符和关键字 标识符 在编程语言中标识符就是定义的具有某种意义的词,比如变量名.常量名.函数名等等. Go语言中标识符允许由字母数字和_(下划线) ...

  9. nexus设置npm下载管理

    nexus设置npm下载管理 第一步 登录私服网页 第二步 创建存储空间(如果使用默认的存储空间,此步骤可省略) 第三步 输入空间的名称,点击create创建 第四步 创建仓库 npm的仓库有三种: ...

  10. from athletelist import AthleteList出现红色下滑波浪线警告

    问题:from athletelist import AthleteList出现红色下滑波浪线警告 经过个人网上搜索了解,这个问题是因为python找不到相关的.py文件,无法导入athletelis ...