[bzoj2088]P3505 [POI2010]TEL-Teleportation
题意
给一张图,要求你再尽可能的多连边,使得从1到2至少要经过5条边
没啥复杂的公式,讲解都在注释里
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<map>
#include<iomanip>
#include<cstring>
#define reg register
#define EN std::puts("")
#define LL long long
inline int read(){
register int x=0;register int y=1;
register char c=std::getchar();
while(c<'0'||c>'9'){if(c=='-') y=0;c=std::getchar();}
while(c>='0'&&c<='9'){x=x*10+(c^48);c=std::getchar();}
return y?x:-x;
}
//P3505 [POI2010]TEL-Teleportation https://www.luogu.com.cn/problem/P3505
//bzoj2088 https://darkbzoj.tk/problem/2088
//题目的意思实际上就是,给出一张图,问最多能加几条边,使得 1->2 的最短路径长度,大于等于 5
//用一点分层图的思想
//考虑将图分成 5 层
//一层:点 1
//二层:和 1 相连的点
//五层:点 2
//四层:和 2 相连的点
//三层:剩下的点
//然后如何加边在代码的注释里,大体思路就是先考虑一层内的加边,然后再考虑层与层之间的
//最后再减去原有的边数,至于怎么严格证明这样是最优的并不会...
//type 表示的是所在层的编号
int type[40006];
int x[1000006],y[1000006];
int n,m;
int link[40006];//这个表示的是 3 层中的点与 2,4 哪一层相连,具体看下面的注释
inline void swap(int &x,int &y){x^=y;y^=x;x^=y;}
int main(){
n=read();m=read();
for(reg int i=3;i<=n;i++) type[i]=3;
type[1]=1;type[2]=5;
int edgenum_2=0,edgenum_3=0,edgenum_4=0;//两个端点均为某层的边的个数
int edgenum_23=0,edgenum_34=0;//两层之间的边数
for(reg int i=1;i<=m;i++){//先处理出各个点都在哪一层
x[i]=read();y[i]=read();
if(x[i]>y[i]) swap(x[i],y[i]);
if(x[i]==1) type[y[i]]=2;
else if(x[i]==2) type[y[i]]=4;
}
for(reg int i=1;i<=m;i++){//处理边数
if(type[x[i]]==2&&type[y[i]]==2) edgenum_2++;
else if(type[x[i]]==3&&type[y[i]]==3) edgenum_3++;
else if(type[x[i]]==4&&type[y[i]]==4) edgenum_4++;
else if((type[x[i]]==2&&type[y[i]]==3)||(type[x[i]]==3&&type[y[i]]==2)) edgenum_23++;
else if((type[x[i]]==4&&type[y[i]]==3)||(type[x[i]]==3&&type[y[i]]==4)) edgenum_34++;
}
int vertex_2=0,vertex_3=0,vertex_4=0;//处理各个层的点的个数
for(reg int i=1;i<=n;i++){
if(type[i]==2) vertex_2++;
else if(type[i]==3) vertex_3++;
else if(type[i]==4) vertex_4++;
}
int ans=0;
//先处理每层内部连边
ans+=vertex_2*(vertex_2-1)/2-edgenum_2;
ans+=vertex_4*(vertex_4-1)/2-edgenum_4;//2,4 层内的点能随便互相连,肯定不会使路径小于 5
//3 层内的点,我们要保证从 2 层走到 3 层后,不能立刻走到 4 层,否则就会出现长度为 4 的路径
//也就是说要有一步是从 3 层的点起步,然后终点也是 3 层的点
//那么,如果和 2 层的某个点相连,就不能和与 4 层的任何点相连,反之,和 4 相连不和 2 相连
//题目规定有解,所以并不会有点同时与 2,4 相连(在原有的边的情况下)
//那么我们可以考虑先处理出在第 3 层中,哪些点与 2 层中的点相连,哪些和 4 中的点相连
for(reg int i=1;i<=m;i++){
if(type[x[i]]==3){
if(type[y[i]]==4) link[x[i]]=4;
else if(type[y[i]]==2) link[x[i]]=2;
}
if(type[y[i]]==3){
if(type[x[i]]==4) link[y[i]]=4;
else if(type[x[i]]==2) link[y[i]]=2;
}
}
int link_2=0,link_4=0,link_no=0;//分别是:在第三层中,与第二层的点相连的点数,与第四层的点相连的点数,不与二或四层的点相连的点数
for(reg int i=1;i<=n;i++)if(type[i]==3){
if(link[i]==2) link_2++;
else if(link[i]==4) link_4++;
else link_no++;
}
ans+=link_no*(link_no-1)/2;//不与 2,4 相连的点随便连
//下面两行就是前面讲的,如果一个点和 2 层相连,那么它可以再与其余的在第三层,并且与 2 层相连的点相连,也可以和不与 2,4 层相连的点相连
//和 4 层相连的点也是同理
//这部分自己拿样例画画图比较好
ans+=link_2*(link_2-1)/2+link_2*link_no;
ans+=link_4*(link_4-1)/2+link_4*link_no;
ans+=link_2*link_4;//和 2 层相连的也可以与和 4 层相连的点随便连
ans-=edgenum_3;//去掉原有的,两个端点都在第 3 层的边数
/********************************************************************/
//下面是不同层之间的连边
//显然,不能跨过一层连边,那样肯定有小于 5 的路径,只能在相邻的层之间连
//1,2 层和 4,5 层肯定不会再有能连的边了
//对于第 3 层:
ans+=link_2*vertex_2-edgenum_23;//和 2 层相连接的点,可以和其它的 2 层的点都连起来,然后再减去 2,3 层之间的边去重
ans+=link_4*vertex_4-edgenum_34;//和 4 层相连的,同理
ans+=link_no*std::max(vertex_2,vertex_4);
//解释上一行:对于不和 2 或 4 层相连的点,只能和 2 或 4 层其中一层的所有点相连,为例最大化边数,肯定是都和 2,4 中点多的一层中的所有点链接
std::printf("%d",ans);
return 0;
}
[bzoj2088]P3505 [POI2010]TEL-Teleportation的更多相关文章
- 洛谷 P3505 [POI2010]TEL-Teleportation
P3505 [POI2010]TEL-Teleportation 题目描述 King Byteasar is the ruler of the whole solar system that cont ...
- Teleportation(tel)
Teleportation(tel) 题目描述 Zy大帝拥有n个星球,因为距离非常遥远,所以Zy在他所居住的1号星球和他的军事基地霸中所在的2号星球建造了两个传送门,这样从1号星球到2号星球就只需要2 ...
- [luogu3505][bzoj2088][POI2010]TEL-Teleportation【分层图】
题目大意 给出了一个图,然后让你加最多的边,让点\(1\)到\(2\)之间至少要经过5条边 解法 比较清楚,我们可以将这个图看作一个分层图,点\(1\)为第一层,再将\(2\)作为第五层,这样第一层和 ...
- POI2010题解
POI2010题解 我也不知道我为什么就开始刷POI了 有些题目咕掉了所以不完整(我都不知道POI到底有多少题) [BZOJ2079][Poi2010]Guilds (貌似bz跟洛谷上的不是一个题?) ...
- 拨打电话tel: 跳转到邮件mailto:(html)
拨打电话 <a href="tel://0571866000">0571-866000</a> 跳转到邮件 <a href="mailto: ...
- 国内固定电话正则验证:'tel': [/0\d{2,3}-\d{7,8}(|([-\u8f6c]{1}\d{1,5}))$/, "请填写有效的电话号码"],
// 验证字段 $('#info_form').validator({ rules : { checkMobile : function(ele) { return checkMobile(ele); ...
- Android网页中tel,sms,mailTo,Intent,Market协议用法总结
tel:协议---拨打电话 <a href="tel:">调出拨号界面</a> <a href="tel:10086">调 ...
- BZOJ 2080: [Poi2010]Railway 双栈排序
2080: [Poi2010]Railway Time Limit: 10 Sec Memory Limit: 259 MBSubmit: 140 Solved: 35[Submit][Statu ...
- 安卓版微信内置浏览器,<a href="tel:电话号码"></a> 这个链接失效,不能跳到拨号界面?
https://segmentfault.com/q/1010000000318831 在URL最后面加“ #mp.weixin.qq.com ”,应该加其他qq.com的二级域名都行,估计是微信的安 ...
随机推荐
- BFC的理解与应用
什么是BFC(Block formatting contexts) BFC的通俗理解: 首先BFC是一个名词,是一个独立的布局环境,我们可以理解为一个箱子(实际上是看不见摸不着的),箱子里面物品的摆放 ...
- 基于linux或windows的c/s的循环服务器求一元二次方程的根
在linux和windows上实现 c/s模式 socket循环服务器求解一元二次方程的根 ax^2+bx+c=0 根据上式,客户端发送a,b,c给服务器,返回求解的根 暂未考虑非法数据等问题 lin ...
- Extjs简单的form+grid组合
采用的是Extjs4.2版本 http://localhost:49999/GridPanel/Index 该链接是本地连接,只是方便自己访问,读者无法正常访问. <script src=&qu ...
- 常用App用户体验找茬
冯晓云: 哔哩哔哩手机客户端:视频播放只允许横屏全屏:还有长视频的“5分钟诅咒”,遇到网速不好的时候是个大写的悲剧: 必应词典UWP版本:主页新闻链接跳转后,一些页面不支持划词取译,当然本身各个页面也 ...
- 数据挖掘入门系列教程(九)之基于sklearn的SVM使用
目录 介绍 基于SVM对MINIST数据集进行分类 使用SVM SVM分析垃圾邮件 加载数据集 分词 构建词云 构建数据集 进行训练 交叉验证 炼丹术 总结 参考 介绍 在上一篇博客:数据挖掘入门系列 ...
- 跨行程序员Java进阶--基础语法
1.基础语法 Hello Wolrd 首先定义类 -- public class 类名 在类定义之后加上一对大括号 -- {} 在大括号中间添加一个主(main)方法/函数 -- public sta ...
- Mysql使用终端操作数据库
使用终端操作数据库 1.如何查看有什么数据库? show databases; 2.如何选择数据库? use databasesName; 3. ...
- MVC-路由扩展-限制浏览器
根据路由原理,MVC每次都会走获取路由上下文数据. 自定义Route 调用,以及完善其他代码 运行结果,当在谷浏览器执行时:
- 大数据Hbase相关运维题
1.启动先电大数据平台的 Hbase 数据库,其中要求使用 master 节点的RegionServer.在 Linux Shell 中启动 Hbase shell,查看 HBase 的版本信息.(相 ...
- 最通俗易懂的Redis发布订阅及代码实战
发布订阅简介 除了使用List实现简单的消息队列功能以外,Redis还提供了发布订阅的消息机制.在这种机制下,消息发布者向指定频道(channel)发布消息,消息订阅者可以收到指定频道的消息,同一个频 ...