题意:有一个未知的边权为$1$的图,给定所有点到$1$的最短路$a_i$和到$2$的最短路$b_i$,问是否存在这样的图,如果存在,问图中最少有多少条边

先考虑$a_i$,有$a_1=0,a_i\neq0(i\neq1)$,对于一条边$(x,y)$有$|a_x-a_y|\leq1$,对于任意$x\neq1$,存在$(x,y)$使得$a_x-1=a_y$,对$b_i$也有类似的约束

所以,我们将点$i$作为$(a_i,b_i)$画在平面上,那么至少要有两条边:第一条连到$(a_i-1,b_i-1)$或$(a_i-1,b_i)$或$(a_i-1,b_i+1)$,第二条连到$(a_i-1,b_i-1)$或$(a_i,b_i-1)$或$(a_i+1,b_i-1)$,如果这时找不到可以连边的点,那么就无解了(点$1$不用连第一种边,点$2$不用连第二种边)

如果可以连,那么我们构造出了一个有$2n-2$条边的图,显然这个图是满足条件的

但我们要最小化图中边数,所以考虑寻找尽可能多的可以共用的边

以下我们将第一种边称为$a$边,第二种边称为$b$边,共用边只可能是两种情况:1.对于点$i$,存在$(a_i-1,b_i-1)$,此时$i$的$a$边和$b$边可以共用;2.存在$i,j$使得$a_i-1=a_j,b_i+1=b_j$,此时$i$的$a$边可以和$j$的$b$边共用

我们把这$2n-2$条边看成点,如果两条边可以共用,在代表它们的点之间连一条边,求最大匹配即可,虽然是一般图,但注意到只有那些满足$a_i+b_i$相等的点$i$引出的边才可能共用,所以建出来的图是这样的(图来自官方题解)

图中框代表某个坐标$(a_i,b_i)$上的点,红点代表$b$边,蓝点代表$a$边,如果方框内有连边说明存在$(a_i-1,b_i-1)$

这种分层图可以从左上往右下贪心选边求最大匹配,实现时只需维护每个坐标的未匹配点个数即可

总时间复杂度为$O(n\log n)$,感觉这题还是不错的

#include<stdio.h>
#include<map>
using namespace std;
map<int,map<int,int> >mp,vis;
int a[100010],b[100010];
bool ex(int x,int y){
	return mp.count(x)&&mp[x].count(y);
}
int main(){
	int n,i,j,s,las,now;
	scanf("%d",&n);
	#define wa {puts("-1");return 0;}
	for(i=1;i<=n;i++){
		scanf("%d%d",a+i,b+i);
		if(i!=1&&a[i]==0)wa
		if(i!=2&&b[i]==0)wa
		mp[a[i]][b[i]]++;
	}
	for(i=1;i<=n;i++){
		if(i!=2){
			if(!(ex(a[i]-1,b[i]-1)||ex(a[i],b[i]-1)||ex(a[i]+1,b[i]-1)))wa
		}
		if(i!=1){
			if(!(ex(a[i]-1,b[i]+1)||ex(a[i]-1,b[i])||ex(a[i]-1,b[i]-1)))wa
		}
	}
	s=0;
	for(i=1;i<=n;i++){
		if(!ex(a[i]-1,b[i]+1)&&!vis[a[i]][b[i]]){
			vis[a[i]][b[i]]=1;
			las=0;
			for(j=0;ex(a[i]+j,b[i]-j);j++){
				now=mp[a[i]+j][b[i]-j];
				s+=min(las,now);
				now-=min(las,now);
				if(ex(a[i]+j-1,b[i]-j-1)){
					s+=now;
					now=min(las,mp[a[i]+j][b[i]-j]);
				}else
					now=mp[a[i]+j][b[i]-j];
				las=now;
			}
		}
	}
	printf("%d",2*n-2-s);
}

[CODE FESTIVAL 2016]Distance Pairs的更多相关文章

  1. 【AtCoder】CODE FESTIVAL 2016 qual A

    CODE FESTIVAL 2016 qual A A - CODEFESTIVAL 2016 -- #include <bits/stdc++.h> #define fi first # ...

  2. 【AtCoder】CODE FESTIVAL 2016 qual B

    CODE FESTIVAL 2016 qual B A - Signboard -- #include <bits/stdc++.h> #define fi first #define s ...

  3. 【AtCoder】CODE FESTIVAL 2016 qual C

    CODE FESTIVAL 2016 qual C A - CF -- #include <bits/stdc++.h> #define fi first #define se secon ...

  4. Atcoder CODE FESTIVAL 2016 Grand Final E - Water Distribution

    Atcoder CODE FESTIVAL 2016 Grand Final E - Water Distribution 题目链接:https://atcoder.jp/contests/cf16- ...

  5. Atcoder CODE FESTIVAL 2016 qual C 的E题 Encyclopedia of Permutations

    题意: 对于一个长度为n的排列P,如果P在所有长度为n的排列中,按照字典序排列后,在第s位,则P的value为s 现在给出一个长度为n的排列P,P有一些位置确定了,另外一些位置为0,表示不确定. 现在 ...

  6. CODE FESTIVAL 2016 qualA Grid and Integers

    划年代久远的水 题意 有一个R*C的棋盘,要求在每个格子上填一个非负数,使得对任意一个2*2的正方形区域,左上角和右下角的数字之和等于左下角和右上角的数字之和.有一些格子已经被填上了数字,问现在能否满 ...

  7. [CODE FESTIVAL 2016]Problem on Tree

    题意:给一棵树,对于一个满足以下要求的序列$v_{1\cdots m}$,求最大的$m$ 对$\forall1\leq i\lt m$,路径$(v_i,v_{i+1})$不包含$v$中除了$v_i,v ...

  8. [CODE FESTIVAL 2016]Encyclopedia of Permutations

    题意:给定一个排列,其中有可能有一些未确定的数,求出所有可能的排列的排名之和 首先我们要知道怎么算一个给定排列的排名,设它为$p_{1\cdots n}$ 排名即为比它小的排列数$+1$,对于每一个比 ...

  9. CODE FESTIVAL 2016 Grand Final 题解

    传送门 越学觉得自己越蠢--这场除了\(A\)之外一道都不会-- \(A\) 贪心从左往右扫,能匹配就匹配就好了 //quming #include<bits/stdc++.h> #def ...

随机推荐

  1. win10以前连接过的wifi密码怎么查看

    右键点击开始,在菜单中选择打开命令提示符,以管理员的权限打开.  然后输入命令netsh wlan show profile显示以前此电脑连接过的所有WIFI记录配置信息.    确定要查看的WIFI ...

  2. kolakoski序列

                   搜狐笔试=.= 当时少想一个slow的指针..呜呜呜哇的一声哭出来 function kolakoski(token0, token1) { token0 = token ...

  3. 大话Spring Cloud

    研究了一段时间Spring Boot了准备向Spring Cloud进发,公司架构和项目也全面拥抱了Spring Cloud.在使用了一段时间后发现Spring Cloud从技术架构上降低了对大型系统 ...

  4. arch中pacman的使用

    Pacman 是archlinux 下的包管理软件.它将一个简单的二进制包格式和易用的构建系统结合了起来.不管软件包是来自官方的 Arch 库还是用户自己创建,Pacman 都能方便得管理. pacm ...

  5. python模块 zipfile

    zipfile是python里用来做zip格式编码的压缩和解压缩的,由于是很常见的zip格式,所以这个模块使用频率也是比较高的zipfile里有两个非常重要的class, 分别是ZipFile和Zip ...

  6. rhel-server srpms iso

    http://ftp.redhat.com/pub/redhat/linux/enterprise/7Server/en/ ftp://ftp.pslib.cz/pub/linux/redhat-cz ...

  7. delphi2006语言新特性:Record类型高级用法

    delphi语言在传统的Records类型的基础上增加了许多像类一样的高级功能,如:Records可以有属性和方法(包括构造constructors),类属性,类方法,类静态字段和内嵌类型.下面这个示 ...

  8. C 封装一个通用链表 和 一个简单字符串开发库

    引言 这里需要分享的是一个 简单字符串库和 链表的基库,代码也许用到特定技巧.有时候回想一下, 如果我读书的时候有人告诉我这些关于C开发的积淀, 那么会走的多直啊.刚参加工作的时候做桌面开发, 服务是 ...

  9. vue知识点(1)

    处理用户输入 v-on指令添加一个事件监听器 div id="app-5"> <p>{{ message }}</p> <button v-on ...

  10. DNS解析原理与Bind部署DNS服务

    DNS是什么? DNS(Domain Name System,域名系统)是互联网上最核心的带层级的分布式系统,它负责把域名转换为IP地址.反查IP到域名的反向解析以及宣告邮件路由等信息,使得基于域名提 ...