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]重要的城市 解题报告的更多相关文章

  1. 【floyd】【bitset】洛谷 P1841 [JSOI2007]重要的城市 题解

        bitset玄学完美优化复杂度? 题目描述 参加jsoi冬令营的同学最近发现,由于南航校内修路截断了原来通向计算中心的路,导致去的路程比原先增加了近一公里.而食堂门前施工虽然也截断了原来通向计 ...

  2. 洛谷 P2323 [HNOI2006]公路修建问题 解题报告

    P2323 [HNOI2006]公路修建问题 题目描述 输入输出格式 输入格式: 在实际评测时,将只会有m-1行公路 输出格式: 思路: 二分答案 然后把每条能加的大边都加上,然后加小边 但在洛谷的题 ...

  3. 洛谷 P1407 [国家集训队]稳定婚姻 解题报告

    P1407 [国家集训队]稳定婚姻 题目描述 我国的离婚率连续7年上升,今年的头两季,平均每天有近5000对夫妇离婚,大城市的离婚率上升最快,有研究婚姻问题的专家认为,是与简化离婚手续有关. 25岁的 ...

  4. 洛谷 P3237 [HNOI2014]米特运输 解题报告

    P3237 [HNOI2014]米特运输 题目描述 米特是\(D\)星球上一种非常神秘的物质,蕴含着巨大的能量.在以米特为主要能源的D星上,这种米特能源的运输和储存一直是一个大问题. \(D\)星上有 ...

  5. 洛谷 P1852 [国家集训队]跳跳棋 解题报告

    P1852 [国家集训队]跳跳棋 题目描述 跳跳棋是在一条数轴上进行的.棋子只能摆在整点上.每个点不能摆超过一个棋子. 我们用跳跳棋来做一个简单的游戏:棋盘上有3颗棋子,分别在\(a\),\(b\), ...

  6. 洛谷 P3299 [SDOI2013]保护出题人 解题报告

    P3299 [SDOI2013]保护出题人 题目描述 出题人铭铭认为给SDOI2012出题太可怕了,因为总要被骂,于是他又给SDOI2013出题了. 参加SDOI2012的小朋友们释放出大量的僵尸,企 ...

  7. 洛谷 P2059 [JLOI2013]卡牌游戏 解题报告

    P2059 [JLOI2013]卡牌游戏 题意 有\(n\)个人玩约瑟夫游戏,有\(m\)张卡,每张卡上有一个正整数,每次庄家有放回的抽一张卡,干掉从庄家起顺时针的第\(k\)个人(计算庄家),干掉的 ...

  8. 洛谷 P2463 [SDOI2008]Sandy的卡片 解题报告

    P2463 [SDOI2008]Sandy的卡片 题意 给\(n(\le 1000)\)串,定义两个串相等为"长度相同,且一个串每个数加某个数与另一个串完全相同",求所有串的最长公 ...

  9. 洛谷 P2774 方格取数问题 解题报告

    P2774 方格取数问题 题目背景 none! 题目描述 在一个有 \(m*n\) 个方格的棋盘中,每个方格中有一个正整数.现要从方格中取数,使任意 2 个数所在方格没有公共边,且取出的数的总和最大. ...

随机推荐

  1. 使用 adb 命令一次性为多个设备安装 apk

    使用 adb 命令一次性为多个设备安装 apk 原创 2016年07月15日 10:40:53 3154 命令简介 adb install [-lrtsdg] (file) 把包文件推送到设备上并安装 ...

  2. 2019年猪年海报PSD模板-第八部分

    11套精美猪年海报,免费猪年海报,下载地址:百度网盘,https://pan.baidu.com/s/1Y3wc_r7O-Dp0mLCihJ9mtQ            

  3. C++ 基础面试题-1

    请说出下面代码在32位系统下的输出内容 /* ** 2018/03/21 21:43:00 ** Brief: ** Author:ZhangJianWei ** Email:Dream_Dog@16 ...

  4. 负数取余/整除,Python和C语言的不同

    总结一句:Python中负数整除,是向负无穷取整,所以导致负数取余不对 在数学公式中,两种语言的表示算法都是一样的,都是: r=a-n*[a/n] 以上,r是余数,a是被除数,n是除数. 唯一不同点, ...

  5. katalon系列六:Katalon Studio Web UI关键字讲解

    在一个Test Case里,点左上Add-Web UI Keyword,可以添加一行新的命令. 像Click.setText.Delay这些最基本的,大家还是看看官方的API文档吧,望文知义,如果是纯 ...

  6. 韦大仙--python对文件操作 2--写入与修改

    请大家看一段代码: yesterday2是我之前上个帖子创建的文件,为了方便大家看清我把本来的代码复制到下面: coding=utf-8 f=open("yesterday2",& ...

  7. Unity编辑器 - 输入控件聚焦问题

    Unity编辑器整理 - 输入控件聚焦问题 EditorGUI的输入控件在聚焦后,如果在其他地方改变值,聚焦的框不会更新,而且无法取消聚焦,如下图: 在代码中取消控件的聚焦 取消聚焦的"时机 ...

  8. 关于javascript的一个小问题,请问有人看出啥问题吗?

    最近学习javascript,有一个问题挺奇怪的,先贴出代码: function binarySearch(){ var arr = [0,1,2,3]; var res = actbinarySea ...

  9. 【if控制器】-(某种情况成立就执行的场景)

    if 控制器   一般来判断某种特殊情况 成立,就执行. JEXL Expression to evaluate:此处直接填写需要进行判断的表达式即可 表达式支持: ==  是否等于,如${__jex ...

  10. 爬虫1.1-基础知识+requests库

    目录 爬虫-基础知识+requests库 1. 状态返回码 2. URL各个字段解释 2. requests库 3. requests库爬虫的基本流程 爬虫-基础知识+requests库 关于html ...