WOJ#4709 迷路

题目描述

dolls意外得到了一张藏宝图,于是他踏上了寻找宝藏的道路。在走了许多许多步,回到同一个位置以后,dolls确定自己迷路了。dolls十分生气,他觉得自己这么英明圣武的人就算迷路,也要迷路在最小的环上。于是他想知道从每个点出发最小的环有多长。藏宝图可以抽象成一个n个点m条边的,边权全为正的无向图,现在你需要求得经过每个点的最小环长是多少。

输入格式

第一行两个数n,m,表示点数和边数。下面m行每行三个整数u,v,l表示点u和点v之间有一条长度为l的无向边。

输出格式

输出n个数,表示经过每个点的最小环长,若没有则输出-1。

数据范围

n≤300,m≤40000

题解

  从i点出发的最短路会构成一棵以i为根的最短路树。易知,经过i点的最小环应该是由最短路上的路径加上一条非树边构成的。由此我们可以想出这样一个算法:对于每个点i,我们构建出以它为根的最短路树,枚举非树边,如果该边之两端点之LCA为i,则用i到两点之最短路之和加上该边边权尝试更新答案。这一部分的时间复杂度应为O(nmlogn)。注意到n只有300而m只有40000,故这个算法完全可行。

  注意一些细节:

  1、记得开long long。

  2、预先特判自环,重边只保留最小的两条。

  3、关于最短路算法的选用:经计算,在该数据范围下,Floyd比跑n遍dijkstra快得多。

  放上代码:

#include<bits/stdc++.h>
using namespace std;
#define N 310
#define M 100010
#define LL long long
#define INF 0x3f3f3f3f
#define pii pair<int,int>
#define mp make_pair
#define pb push_back
int num=,f[N];
struct node{
int u,v,w,nxt;
}e[M<<];
void add(int u,int v,int w){e[++num]=(node){u,v,w,f[u]};f[u]=num;}
//build graph
LL ans[N],Mp[N][N],dis[N][N];
void floyd(int n){
for(int k=;k<=n;k++)
for(int i=;i<=n;i++)
for(int j=;j<=n;j++) dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
}
//shortest path
int inq[M<<],Add[N];
vector<int> g[N];
void build(int u,int st){
for(int i=f[u];i;i=e[i].nxt){
int v=e[i].v,w=e[i].w;
if(dis[st][v]==dis[st][u]+w&&!Add[v]){
inq[i]=inq[i^]=;Add[v]=;g[u].pb(v);g[v].pb(u);build(v,st);
}
}
}
//build tree
int dep[N],faz[N],sze[N],son[N],Top[N];
void dfs1(int u,int fa,int d){
dep[u]=d;sze[u]=;faz[u]=fa;
for(int i=;i^g[u].size();i++){
int v=g[u][i];
if(v==fa) continue;
dfs1(v,u,d+);sze[u]+=sze[v];
if(!son[u]||sze[v]>sze[son[u]]) son[u]=v;
}
}
void dfs2(int u,int st){
Top[u]=st;
if(!son[u]) return;
dfs2(son[u],st);
for(int i=;i^g[u].size();i++){
int v=g[u][i];
if(v==faz[u]||v==son[u]) continue;
dfs2(v,v);
}
}
int LCA(int x,int y){
int xx=Top[x],yy=Top[y];
while(xx!=yy){
if(dep[xx]<dep[yy]){swap(xx,yy);swap(x,y);}
x=faz[xx];xx=Top[x];
}
if(dep[x]>dep[y]) return y;
return x;
}
//tree dissection
inline int read(){
int x=,f=;char ch;
for(ch=getchar();(ch<''||ch>'')&&ch!='-';ch=getchar());
if(ch=='-'){f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=(x<<)+(x<<)+ch-'';ch=getchar();}
return x*f;
}
//读优
int n,m;
void write(int i){
if(ans[i]^ans[]) printf("%lld ",ans[i]);
else printf("-1 ");
}
int main(){
int x,y,z,sum=;
n=read();m=read();
memset(Mp,0x3f,sizeof(Mp));
memset(ans,0x3f,sizeof(ans));
memset(dis,0x3f,sizeof(dis));
for(int i=;i<=m;i++){
x=read();y=read();z=read();
if(i<=n) dis[i][i]=;
if(x==y){ans[x]=min(ans[x],(LL)z);continue;}
if(Mp[x][y]<=z) continue;
sum++;add(x,y,z),add(y,x,z);LL tmp=dis[x][y];
dis[x][y]=dis[y][x]=min(tmp,(LL)z);
Mp[x][y]=Mp[y][x]=max(tmp,(LL)z);
}
floyd(n);
for(int i=;i<=n;i++){
memset(Add,,sizeof(Add));
memset(dep,,sizeof(dep));
memset(faz,,sizeof(faz));
memset(sze,,sizeof(sze));
memset(son,,sizeof(son));
memset(Top,,sizeof(Top));
memset(inq,,sizeof(inq));
for(int j=;j<=n;j++) g[j].clear();
build(i,i);dfs1(i,i,);dfs2(i,i);
for(int j=;j<=num;j+=){
int u=e[j].u,v=e[j].v,w=e[j].w;LL tmp=dis[i][u]+dis[i][v]+w;
if(inq[j]||ans[i]<=tmp||LCA(u,v)^i) continue;
ans[i]=tmp;
}
write(i);
}
return ;
}

  

WOJ#4709 迷路的更多相关文章

  1. WOJ -1204

    WOJ -1204 1 出现次数大于一半 那么就利用普通的堆栈的思想,如果删除两个不同的元素,原来的多数元素还是多数元素,所以采取按条件入栈的方法,如果和top元素相同则入栈,否则top--,此元素也 ...

  2. hdu - 4709 - Herding

    题意:给出N个点的坐标,从中取些点来组成一个多边形,求这个多边形的最小面积,组不成多边形的输出"Impossible"(测试组数 T <= 25, 1 <= N < ...

  3. BZOJ 1297: [SCOI2009]迷路( dp + 矩阵快速幂 )

    递推式很明显...但是要做矩阵乘法就得拆点..我一开始很脑残地对于每一条权值v>1的边都新建v-1个节点去转移...然后就TLE了...把每个点拆成9个就可以了...时间复杂度O((9N)^3* ...

  4. 【百度地图API】圣诞节里不会迷路的麋鹿——驾车导航

    原文:[百度地图API]圣诞节里不会迷路的麋鹿--驾车导航 任务描述: 可能大家还不知道,圣诞老人是爱迷路的老爷爷! 今年圣诞节又要到了,圣诞老人又要出来送礼物了.可是,他灰常的迷路呢! 还好,他有一 ...

  5. 1297: [SCOI2009]迷路

    1297: [SCOI2009]迷路 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 652  Solved: 442[Submit][Status] ...

  6. 【矩阵快速幂】bzoj1297 [SCOI2009]迷路

    1297: [SCOI2009]迷路 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1407  Solved: 1007[Submit][Status ...

  7. [BZOJ 1297][SCOI2009]迷路

    1297: [SCOI2009]迷路 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1418  Solved: 1017[Submit][Status ...

  8. B20J_1297_[SCOI2009]迷路_矩阵乘法

    B20J_1297_[SCOI2009]迷路_矩阵乘法 题意:有向图 N 个节点,从节点 0 出发,必须恰好在 T 时刻到达节点 N-1.总共有多少种不同的路径? 2 <= N <= 10 ...

  9. bzoj 4709 [Jsoi2011]柠檬——单调栈二分处理决策单调性

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4709 题解:https://blog.csdn.net/neither_nor/articl ...

随机推荐

  1. 与Swing的初见

    ---------------------------参考菜鸟教程的swing课程学习-------------------- Swing 是一个为Java设计的GUI工具包. Swing是JAVA基 ...

  2. linux运维、架构之路-nfs网络文件系统

    一.nfs介绍  NFS是Network File System的缩写,是网络文件系统,它的主要功能是通过网络(一般是局域网)让不同的主机系统之间可以共享文件或目录,主要存储用户上传的图片附件等信息. ...

  3. 阿里重磅开源全球首个批流一体机器学习平台Alink,Blink功能已全部贡献至Flink

    11月28日,Flink Forward Asia 2019 在北京国家会议中心召开,阿里在会上发布Flink 1.10版本功能前瞻,同时宣布基于Flink的机器学习算法平台Alink正式开源,这也是 ...

  4. javascript之大文件分段上传、断点续传(一)

    需求: 支持大文件批量上传(20G)和下载,同时需要保证上传期间用户电脑不出现卡死等体验: 内网百兆网络上传速度为12MB/S 服务器内存占用低 支持文件夹上传,文件夹中的文件数量达到1万个以上,且包 ...

  5. USACO Overplanting ( 线段树扫描线 )

    题意 : 在二维平面上给出 N 个矩形,问你所有矩形构成的图案的面积是多少(相互覆盖的地方只计算一次) 分析 :  求矩形面积并可以模拟来做,不过使用线段树来辅助做扫描线可以更高效地求解 扫描线顾名思 ...

  6. [luogu]P2680 运输计划[二分答案][树上差分]

    [luogu]P2680 [NOIP2015]运输计划 题目背景 公元 2044 年,人类进入了宇宙纪元. 题目描述 L 国有 n 个星球,还有 n-1 条双向航道,每条航道建立在两个星球之间,这 n ...

  7. R Seurat 单细胞处理pipline 代码

    options(stringsAsFactors = F ) rm(list = ls()) library(Seurat) library(dplyr) library(ggplot2) libra ...

  8. 消息队列之 ActiveMQ

    简介 ActiveMQ 特点 ActiveMQ 是由 Apache 出品的一款开源消息中间件,旨在为应用程序提供高效.可扩展.稳定.安全的企业级消息通信. 它的设计目标是提供标准的.面向消息的.多语言 ...

  9. benchmarks

    系统性能测试 stream SPARK 测试 streaming benchmark https://github.com/yahoo/streaming-benchmarks

  10. flex 强制垃圾回收

    java和flash的垃圾回收都是一个比较热门的话题,今天我也用一个例子来测试下flash的强制垃圾回收.主要用到的而一个类是LocalConnection. 在Flash player的debug版 ...