令$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. 易华录 X ShardingSphere|葫芦 App 后台数据处理的逻辑捷径

    "ShardingSphere 大大简化了分库分表的开发和维护工作,对于业务的快速上线起到了非常大的支撑作用,保守估计 ShardingSphere 至少为我们节省了 4 个月的研发成本.& ...

  2. iOS自动化之WDA(WebDriverAgent)安装

    1.WDA介绍 WebDriverAgent 在 iOS 端实现了一个 WebDriver server ,借助这个 server 我们可以远程控制 iOS 设备.你可以启动.杀死应用,点击.滚动视图 ...

  3. DL4J实战之五:矩阵操作基本功

    欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...

  4. 使用ShardingSphere-JDBC完成Mysql的分库分表和读写分离

    1. 概述 老话说的好:选择比努力更重要,如果选错了道路,就很难成功. 言归正传,之前我们聊了使用 MyCat 实现Mysql的分库分表和读写分离,MyCat是服务端的代理,使用MyCat的好处显而易 ...

  5. python的函数参数传递方式

    python的一切数据类型都是对象.但是python的对象分为不可变对象和可变对象.python的变量是引用,对python变量的赋值是引用去绑定该对象. 可变对象的数据发生改变,例如列表和字典,引用 ...

  6. 《JavaScript DOM编程艺术》:innerHTML

    来源:第七章 动态创建标记 innerHTML: 1.HTML页面建立空白div: <div id="testdiv"> </div> <script ...

  7. UltraSoft - Beta - Scrum Meeting 9

    Date: May 25th, 2020. Scrum 情况汇报 进度情况 组员 负责 今日进度 q2l PM.后端 记录Scrum Meeting Liuzh 前端 用户忘记密码界面初稿完成 Kkk ...

  8. [no code][scrum meeting] Alpha 8

    项目 内容 会议时间 2020-04-14 会议主题 API文档第一版交付 会议时长 30min 参会人员 PM+OCR组成员 $( "#cnblogs_post_body" ). ...

  9. SpringBoot加密配置属性

    一.背景 在系统中的运行过程中,存在很多的配置属性,比如: 数据库配置.阿里云配置 等等,这些配置有些属性是比较敏感的,是不应直接以明文的方式出现在配置文件中,因此对于这些配置我们就需要加密来处理. ...

  10. 修炼Servlet

    修炼Servlet 一.Servlet简单认识 1.Servlet是什么 Java Servlet 是运行在 Web 服务器或应用服务器上的程序,它是作为来自 Web 浏览器或其他 HTTP 客户端的 ...