令$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. Java实现红黑树(平衡二叉树)

    前言 在实现红黑树之前,我们先来了解一下符号表. 符号表的描述借鉴了Algorithms第四版,详情在:https://algs4.cs.princeton.edu/home/ 符号表有时候被称为字典 ...

  2. MySQL初步学习——2021.09.27每日总结,第四周周一

    (1)今天做了什么: (2)明天准备做什么? (3)遇到的问题,如何解决? 今天学习了SQL语句的分类: SQL语句很多,分为 1.DQL:数据查询语言(凡是带有select关键字的都是查询语句) 2 ...

  3. 定制input元素

    定制input元素 input元素可以用来生成一个供用户输入数据的简单文本框.其缺点在于用户在其中输入什么值都可以.有时这还不错,但是有时设计者可能希望让用户输入特定类型的数据.在后一种情况下,可以对 ...

  4. 2020.11.6-vj补题

    A - A CodeForces - 136A 题解:按输入的顺序输出对应的下标即可,定义一个数组,将输入的作为下标,下标为值,最后依次输出即可: #include<bits/stdc++.h& ...

  5. .Net2.0连接PG数据注意事项

    .Net2.0连接PG数据注意事项 第一次用.net操作PG[.NET2.0] 一:Npgsql版本问题 1:如果是.net2.0  建议用2.0.11.0[NuGet搜索npgsql第一个的最低版本 ...

  6. Google Object detection配置与使用

    Google Object detection 前言: 本文记录了使用Google发布的Object detection(July 1st, 2019)接口,完成了对标注目标的检测.参考了很多博文,在 ...

  7. HttpClient使用GET方式通过代理服务器读取页面的例子

    import java.io.BufferedReader;import java.io.InputStreamReader;import org.apache.http.HttpEntity;imp ...

  8. 6月2日 Scrum Meeting

    日期:2021年6月2日 会议主要内容概述: 取消账单类别自定义 图表属性分析取消函数输入 增加新的主题模板 一.进度情况 组员 负责 两日内已完成的工作 后两日计划完成的工作 工作中遇到的困难 徐宇 ...

  9. Scrum Meeting 0529

    零.说明 日期:2021-5-29 任务:简要汇报七日内已完成任务,计划后两日完成任务 一.进度情况 组员 负责 七日内已完成的任务 后两日计划完成的任务 困难 qsy PM&前端 完成后端管 ...

  10. 【二食堂】Beta - Scrum Meeting 5

    Scrum Meeting 5 例会时间:5.18 18:30~18:50 进度情况 组员 当前进度 今日任务 李健 1. 划词功能已经实现,继续开发,完善文本区域交互,调用API issue 1. ...