洛谷

bzoj

用了分层图的思想

题意

给一张图,要求你再尽可能的多连边,使得从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的更多相关文章

  1. 洛谷 P3505 [POI2010]TEL-Teleportation

    P3505 [POI2010]TEL-Teleportation 题目描述 King Byteasar is the ruler of the whole solar system that cont ...

  2. Teleportation(tel)

    Teleportation(tel) 题目描述 Zy大帝拥有n个星球,因为距离非常遥远,所以Zy在他所居住的1号星球和他的军事基地霸中所在的2号星球建造了两个传送门,这样从1号星球到2号星球就只需要2 ...

  3. [luogu3505][bzoj2088][POI2010]TEL-Teleportation【分层图】

    题目大意 给出了一个图,然后让你加最多的边,让点\(1\)到\(2\)之间至少要经过5条边 解法 比较清楚,我们可以将这个图看作一个分层图,点\(1\)为第一层,再将\(2\)作为第五层,这样第一层和 ...

  4. POI2010题解

    POI2010题解 我也不知道我为什么就开始刷POI了 有些题目咕掉了所以不完整(我都不知道POI到底有多少题) [BZOJ2079][Poi2010]Guilds (貌似bz跟洛谷上的不是一个题?) ...

  5. 拨打电话tel: 跳转到邮件mailto:(html)

    拨打电话 <a href="tel://0571866000">0571-866000</a> 跳转到邮件 <a href="mailto: ...

  6. 国内固定电话正则验证:'tel': [/0\d{2,3}-\d{7,8}(|([-\u8f6c]{1}\d{1,5}))$/, "请填写有效的电话号码"],

    // 验证字段 $('#info_form').validator({ rules : { checkMobile : function(ele) { return checkMobile(ele); ...

  7. Android网页中tel,sms,mailTo,Intent,Market协议用法总结

     tel:协议---拨打电话 <a href="tel:">调出拨号界面</a> <a href="tel:10086">调 ...

  8. BZOJ 2080: [Poi2010]Railway 双栈排序

    2080: [Poi2010]Railway Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 140  Solved: 35[Submit][Statu ...

  9. 安卓版微信内置浏览器,<a href="tel:电话号码"></a> 这个链接失效,不能跳到拨号界面?

    https://segmentfault.com/q/1010000000318831 在URL最后面加“ #mp.weixin.qq.com ”,应该加其他qq.com的二级域名都行,估计是微信的安 ...

随机推荐

  1. flask 入门之 logging

    如想看详细说明,请到: 1.https://www.cnblogs.com/yyds/p/6901864.html 2.https://docs.python.org/2/library/loggin ...

  2. JAVA集合框架之List和Set、泛型

    一 List是有序可重复的集合 可以进行增删改查,直接看代码 package com.collection; import java.util.ArrayList; import java.util. ...

  3. C语言实现链栈以及基本操作

    链栈,即用链表实现栈存储结构.链栈的实现思路同顺序栈类似,顺序栈是将数顺序表(数组)的一端作为栈底,另一端为栈顶:链栈也如此,通常我们将链表的头部作为栈顶,尾部作为栈底,如下下图所示: 将链表头部作为 ...

  4. centos7.3下安装nginx

    Nginx简介 Nginx是一款轻量级的Web服务器/反向代理服务器/电子邮件(IMAP/POP3)代理服务器,在BSD-like 协议下发行.其特点是占有内存少,并发能力强, Nginx的并发能力在 ...

  5. Golang 性能测试 (3) 跟踪刨析 golang trace

    简介 对于绝大部分服务,跟踪刨析是用不到的.但是如果遇到了下面问题,可以不妨一试: 怀疑哪个协程慢了 系统调用有问题 协程调度问题 (chan 交互.互斥锁.信号量等) 怀疑是 gc (Garbage ...

  6. go中的error小结

    go中的error error和panic error接口 go中err的困局 推荐方法 总结 参考 go中的error go中的错误处理,是通过返回值的形式来出来,要么你忽略,要么你处理(处理也可以 ...

  7. 经常使用到的vim命令

    常用的vim命令 总结了我经常用到的vim命令,虽然不是很全,但是日常的开发足够了 启动vim vim 直接启动vim vim filename 打开vim并创建名为filename的文件 插入命令 ...

  8. Python财经数据接口包TuShare的使用

    安装TuShare 方式1:pip install tushare 方式2:访问https://pypi.python.org/pypi/tushare/下载安装 方式3:将源代码下载到本地pytho ...

  9. 带你走进神一样的Elasticsearch索引机制

    更多精彩内容请看我的个人博客 前言 相比于大多数人熟悉的MySQL数据库的索引,Elasticsearch的索引机制是完全不同于MySQL的B+Tree结构.索引会被压缩放入内存用于加速搜索过程,这一 ...

  10. Unity 随机地图房间通道生成

    之前的博客中已经说了随机房间生成: https://www.cnblogs.com/koshio0219/p/12604383.html 但实现房间生成只是整个地图生成最初最简单的一步.下面讨论如何随 ...