洛谷 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 个数所在方格没有公共边,且取出的数的总和最大. ...
随机推荐
- 「题目代码」P1049~P1053(Java)
P1049 谭浩强C语言(第三版)习题6.5 import java.util.*; import java.io.*; import java.math.BigInteger; import jav ...
- 180611-Spring之RedisTemplate配置与使用
logo 文章链接:https://liuyueyi.github.io/hexblog/2018/06/11/180611-Spring之RedisTemplate配置与使用/ Spring ...
- Python全栈 MongoDB 数据库(Mongo、 正则基础、一篇通)
终端命令: 在线安装: sudo apt-get install mongodb 默认安装路径 : /var/lib/mong ...
- 剑指offer-栈的压入弹出序列21
题目描述 输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序.假设压入栈的所有数字均不相等.例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压 ...
- Netcore logging config
- 6.azkban的监控
azkaban自带的监控flow自带的邮件功能SLA总结写程序监控job情况监控azkaban的元数据库使用azkaban API监控总结 azkaban自带的监控 azkban目前仅仅支持邮件监控, ...
- 【转载】java byte转十六进制
public static String bytes2HexString(byte[] b) { String ret = ""; for (int i = 0; i < b ...
- 第二十次ScrumMeeting会议
第二十次Scrum Meeting 时间:2017/12/10 地点:新主楼1039 人员:蔡帜 王子铭 游心 解小锐 王辰昱 李金奇 杨森 陈鑫 赵晓宇 照片: 目前工作进展 名字 今日 明天的工作 ...
- Coursera-Note: Internet History, Technology and Secure (1st week to 9th week)
目录 Coursera-Note: Internet History, Technology and Secure 第一周 第二周 数据交换: Packet switching技术: 第三周 创造ht ...
- j2ee—框架(1):Servlet+JSP实现基本的登录功能(v1.0)
主要分为四个部分:LoginController.web.xml.login.jsp和login_success.jsp(login_fail.jsp). 第一部分 LoginController p ...