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. VS Help Viewer 显示内容为HTML源码的问题

    万恶的IE10 为了学习,安装了一套Windows Server 2012+SQL 2012+VS 2012的环境,整体感觉还不错,只是在使用Help Viewer查看帮助的时候,发现显示内容居然为H ...

  2. 02-JVM内存模型:虚拟机栈与本地方法栈

    一.虚拟机栈(VM Stack) 1.1)什么是虚拟机栈 虚拟机栈是用于描述java方法执行的内存模型. 每个java方法在执行时,会创建一个“栈帧(stack frame)”,栈帧的结构分为“局部变 ...

  3. uvaoj1585Score(暴力)

    1585 ScoreThere is an objective test result such as “OOXXOXXOOO”. An ‘O’ means a correct answer of a ...

  4. Unity Lighting - Choosing a Rendering Path 选择渲染路径(三)

      Choosing a Rendering Path 选择渲染路径 Unity supports a number of rendering techniques, or ‘paths’. An i ...

  5. POJ 3256 (简单的DFS)

    //题意是 K N, M; //有K个牛 N个牧场,M条路 ,有向的  //把K个牛放到任意的n个不同牧场中,问所有牛都可以到达的牧场数的总和  //这是一道简单的DFS题 //k 100 //n 1 ...

  6. [JSON].valueOf( keyPath )

    语法:[JSON].valueOf( keyPath ) 返回:[任意类型 | null] 说明:获取键名路径原值,它保留原始值的类型 示例: b = sysFile.binary("tes ...

  7. Spring Cloud(七):配置中心(Git 版与动态刷新)【Finchley 版】

    Spring Cloud(七):配置中心(Git 版与动态刷新)[Finchley 版]  发表于 2018-04-19 |  更新于 2018-04-24 |  Spring Cloud Confi ...

  8. C++ ifndef /define/ endif 作用和用法

    ifndef/define/endif”主要目的是防止头文件的重复包含和编译 比如你有两个C文件,这两个C文件都include了同一个头文件.而编译时,这两个C文件要一同编译成一个可运行文件,于是问题 ...

  9. 2018(容斥定理 HDU6286)

    2018 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submis ...

  10. BAT 批处理脚本 教程 【转】

    BAT 批处理脚本 教程 第一章 批处理基础 第一节 常用批处理内部命令简介 批处理定义:顾名思义,批处理文件是将一系列命令按一定的顺序集合为一个可执行的文本文件,其扩展名为BAT或者CMD.这些命令 ...