洛谷 P1841 [JSOI2007]重要的城市 解题报告
P1841 [JSOI2007]重要的城市
题目描述
参加jsoi冬令营的同学最近发现,由于南航校内修路截断了原来通向计算中心的路,导致去的路程比原先增加了近一公里。而食堂门前施工虽然也截断了原来通向计算中心的路,却没有使路程增加,因为可以找到同样长度的路作替代。其实,问题的关键在于,路截断的地方是交通要点。
同样的情况也出现在城市间的交通中。某些城市如果出了问题,可能会引起其他很多城市的交通不便。另一些城市则影响不到别的城市的交通。jsoi冬令营的同学发现这是一个有趣的问题,于是决定研究这个问题。
他们认为这样的城市是重要的:如果一个城市c被破坏后,存在两个不同的城市a和b(a, b均不等于c),a到b的最短距离增长了(或不通),则城市c是重要的。
jsoi冬令营的同学面对着一张教练组交给他们的城市间交通图,他们希望能找出所有重要的城市。现在就请你来解决这个问题。
输入输出格式
输入格式:
第一行两个整数N,M,N为城市数,M为道路数
接下来M行,每行三个整数,表示两个城市之间的无向边,以及之间的路的长度
输出格式:
一行,按递增次序输出若干的数,表示重要的城市。
说明
30%的数据: \(N\le 20\);
60%的数据: \(N\le 100\);
100%的数据: \(N\le 200,M\le \frac{N\times (N-1)}{2},0<c\le 10000\)。c即路的长度。
保证不出现重边和自环
如果没有点的话需要输出一行
“No important cities.”
去掉引号
这个题很神奇
先说说普遍的\(O(N^3)\)的做法。
一个点\(i\)称为重要点的要求:存在一对点\((u,v)\),这对点的所有最短路都经过这个点\(i\)
考虑floyd松弛的过程,如果点\(i\)松弛成功\((u,v)\),说明\(i\)至少在前\(i\)个点松弛过后的最短路上,我们先把它存起来,没错只存它(其实用bitset把所有的点存下来复杂度也是可行的而且跑到飞快),如果没松弛成功且刚好相等,那这个点被开除重要点了,不满足唯一性,踢掉。
其实说起来很不清楚,但我们大致可以感性理解。
关于为什么这样不会漏点,因为之前的点已经存了。比如说1-4被3松弛,存下\(point[1][4]=3\),而1-4最短路上其实有1,2,3,4这几个点,不过我们已经在1,3时存下了2,因此这样其实会有重复,所以我们最后统计时去个重。
Code:
#include <cstdio>
#include <cstring>
#include <algorithm>
const int N=202;
int g[N][N],n,m,point[N][N],ans[N*N],cnt;
int main()
{
scanf("%d%d",&n,&m);
memset(g,0x3f,sizeof(g));
for(int u,v,w,i=1;i<=m;i++)
{
scanf("%d%d%d",&u,&v,&w);
g[u][v]=g[v][u]=w;
}
for(int k=1;k<=n;k++)
{
for(int i=1;i<=n;i++)
{
if(i==k) continue;
for(int j=1;j<=n;j++)
{
if(j==i||j==k) continue;
if(g[i][j]>g[i][k]+g[k][j])
{
g[i][j]=g[i][k]+g[k][j];
point[i][j]=k;
}
else if(g[i][j]==g[i][k]+g[k][j])
point[i][j]=0;
}
}
}
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(point[i][j])
ans[++cnt]=point[i][j];
if(!cnt) printf("No important cities.\n");
std::sort(ans+1,ans+1+cnt);
cnt=std::unique(ans+1,ans+1+cnt)-(ans+1);
for(int i=1;i<=cnt;i++)
printf("%d ",ans[i]);
return 0;
}
再提供一个比较好理解的\(O(n^3logn)\)的分治算法
在Floyd松弛的过程中,其实哪个点先松弛哪个点后松弛是无所谓的哈
而我们最后拆点走其实就是只有一个点不松弛和所有点都松弛情况的一个对比,看各点的最短路情况有没有改变
对未松弛点集\([l,r]\)
我们可以先松弛其中的一半\([l,mid]\),然后去另一半处理子问题,处理完了还原左区间,松弛右区间,再去左边处理问题
这样当区间大小为1时,就只是那个点没有参与松弛,我们对比一下即可
而对每个相同大小的区间构成的集合,它们实际上总共用了每个点松弛了一次,为\(O(N^3)\)(还原是\(O(N^2)\)的,算做常数)
一共有\(logn\)种大小的区间,所以总复杂度为\(O(N^3logn)\)
Code:
#include <cstdio>
#include <cstring>
int min(int x,int y){return x<y?x:y;}
const int N=202;
int g[N][N],n,m,flag,ans[N],d[N][N];
void divide(int l,int r)
{
if(l==r)
{
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(i!=j&&g[i][j]<d[i][j])
{
ans[l]=1;
flag=1;
return;
}
return;
}
int tmp[N][N];
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
tmp[i][j]=d[i][j];
int mid=l+r>>1;
for(int k=l;k<=mid;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
d[i][j]=min(d[i][j],d[i][k]+d[k][j]);
divide(mid+1,r);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
d[i][j]=tmp[i][j];
for(int k=mid+1;k<=r;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
d[i][j]=min(d[i][j],d[i][k]+d[k][j]);
divide(l,mid);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
d[i][j]=tmp[i][j];
}
int main()
{
scanf("%d%d",&n,&m);
memset(g,0x3f,sizeof(g));
memset(d,0x3f,sizeof(d));
for(int u,v,w,i=1;i<=m;i++)
{
scanf("%d%d%d",&u,&v,&w);
d[u][v]=d[v][u]=g[u][v]=g[v][u]=w;
}
for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
g[i][j]=min(g[i][j],g[i][k]+g[k][j]);
divide(1,n);
if(!flag) printf("No important cities.\n");
for(int i=1;i<=n;i++)
if(ans[i])
printf("%d ",i);
return 0;
}
2018.8.4
洛谷 P1841 [JSOI2007]重要的城市 解题报告的更多相关文章
- 【floyd】【bitset】洛谷 P1841 [JSOI2007]重要的城市 题解
bitset玄学完美优化复杂度? 题目描述 参加jsoi冬令营的同学最近发现,由于南航校内修路截断了原来通向计算中心的路,导致去的路程比原先增加了近一公里.而食堂门前施工虽然也截断了原来通向计 ...
- 洛谷 P2323 [HNOI2006]公路修建问题 解题报告
P2323 [HNOI2006]公路修建问题 题目描述 输入输出格式 输入格式: 在实际评测时,将只会有m-1行公路 输出格式: 思路: 二分答案 然后把每条能加的大边都加上,然后加小边 但在洛谷的题 ...
- 洛谷 P1407 [国家集训队]稳定婚姻 解题报告
P1407 [国家集训队]稳定婚姻 题目描述 我国的离婚率连续7年上升,今年的头两季,平均每天有近5000对夫妇离婚,大城市的离婚率上升最快,有研究婚姻问题的专家认为,是与简化离婚手续有关. 25岁的 ...
- 洛谷 P3237 [HNOI2014]米特运输 解题报告
P3237 [HNOI2014]米特运输 题目描述 米特是\(D\)星球上一种非常神秘的物质,蕴含着巨大的能量.在以米特为主要能源的D星上,这种米特能源的运输和储存一直是一个大问题. \(D\)星上有 ...
- 洛谷 P1852 [国家集训队]跳跳棋 解题报告
P1852 [国家集训队]跳跳棋 题目描述 跳跳棋是在一条数轴上进行的.棋子只能摆在整点上.每个点不能摆超过一个棋子. 我们用跳跳棋来做一个简单的游戏:棋盘上有3颗棋子,分别在\(a\),\(b\), ...
- 洛谷 P3299 [SDOI2013]保护出题人 解题报告
P3299 [SDOI2013]保护出题人 题目描述 出题人铭铭认为给SDOI2012出题太可怕了,因为总要被骂,于是他又给SDOI2013出题了. 参加SDOI2012的小朋友们释放出大量的僵尸,企 ...
- 洛谷 P2059 [JLOI2013]卡牌游戏 解题报告
P2059 [JLOI2013]卡牌游戏 题意 有\(n\)个人玩约瑟夫游戏,有\(m\)张卡,每张卡上有一个正整数,每次庄家有放回的抽一张卡,干掉从庄家起顺时针的第\(k\)个人(计算庄家),干掉的 ...
- 洛谷 P2463 [SDOI2008]Sandy的卡片 解题报告
P2463 [SDOI2008]Sandy的卡片 题意 给\(n(\le 1000)\)串,定义两个串相等为"长度相同,且一个串每个数加某个数与另一个串完全相同",求所有串的最长公 ...
- 洛谷 P2774 方格取数问题 解题报告
P2774 方格取数问题 题目背景 none! 题目描述 在一个有 \(m*n\) 个方格的棋盘中,每个方格中有一个正整数.现要从方格中取数,使任意 2 个数所在方格没有公共边,且取出的数的总和最大. ...
随机推荐
- 「日常训练&知识学习」树的分块(王室联邦,HYSBZ-1086)
题意与分析 这题的题意就是树分块,更具体的看题目(中文题). 学习这一题是为了树的分块,为树上莫队做铺垫. 参考1:https://blog.csdn.net/LJH_KOQI/article/det ...
- Spring Cloud(八):配置中心(服务化与高可用)【Finchley 版】
Spring Cloud(八):配置中心(服务化与高可用)[Finchley 版] 发表于 2018-04-19 | 更新于 2018-04-26 | 本文接之前的<Spring Clou ...
- ionic LoadingController 模块使用
html 代码: <ion-header> <ion-navbar> <ion-title>Loading</ion-title> </ion-n ...
- C++字符串拼接和输入
一 .char类型字符串以空字符结尾 1.以空字符结尾,空字符被写作\0,其ASCII码为0,用来标记字符串的结尾. char dog[4]={'a','b','c','d'} //不是一个字符串 ...
- maven 安装、配置
简介: maven 大大提高项目开发速度 编译---打包---测试--安装 一条龙 maven将项目构建的过程标准化,每一个阶段使用一个命令完成,下面是构建过程一些阶段 清理 mvn cl ...
- LintCode-88.最近公共祖先
最近公共祖先 给定一棵二叉树,找到两个节点的最近公共父节点(LCA). 最近公共祖先是两个节点的公共的祖先节点且具有最大深度. 注意事项 假设给出的两个节点都在树中存在 样例 对于下面这棵二叉树 LC ...
- kafka启动出现:Unsupported major.minor version 52.0 错误
具体的错误输出: Exception in thread "main" java.lang.UnsupportedClassVersionError: kafka/Kafka : ...
- Windows Sever 2008隐藏和系统属性
由于有些目录为隐藏和系统属性,首先要把 显示系统文件和显示所有文件 功能开启,把隐藏文件和目录显出来. 1.C:\Windows\Web\Wall*** 自带墙纸,不需要的可以删除掉. 2.C:\Wi ...
- Python 时间推进器-->在当前时间的基础上推前n天 | CST时间转化标准日期格式
由于公司任务紧迫,好久没有在园子里写自己的心得了,今天偷个闲发表点简单的代码块,在开源的时代贡献微薄力量.话不多说,直接上代码块: ]) m = ]) d = ]) the_date = dateti ...
- Linux命令之查看cpu个数_核数_内存总数
http://blog.csdn.net/cgwcgw_/article/details/10000053 cpu个数 cat /proc/cpuinfo | grep "physical ...