【思维题 并查集 图论】bzoj1576: [Usaco2009 Jan]安全路经Travel
有趣的思考题
Description
Input
* 第一行: 两个空格分开的数, N和M
* 第2..M+1行: 三个空格分开的数a_i, b_i,和t_i
Output
* 第1..N-1行: 第i行包含一个数:从牛棚_1到牛棚_i+1并且避免从牛棚1到牛棚i+1最短路经上最后一条牛路的最少的时间.如果这样的路经不存在,输出-1.
题目分析
做法一
暴力树剖线段树
做法二
并查集[bzoj1576] [Usaco2009 Jan]安全路经Travel
#include<bits/stdc++.h>
const int maxn = ;
const int maxm = ; int n,m,dis[maxn];
struct cmp
{
bool operator ()(int a, int b) const
{
return dis[a] > dis[b];
}
};
struct Edge
{
int y,val;
Edge(int a=, int b=):y(a),val(b) {}
}edges[maxm];
struct EdgeSv
{
int x,y,dis;
bool operator < (EdgeSv a) const
{
return dis < a.dis;
}
EdgeSv(int a=, int b=, int c=):x(a),y(b),dis(c) {}
}edgeSv[maxm];
int fa[maxn],fat[maxn],tag[maxn],dep[maxn];
bool disVis[maxn],treeTag[maxm];
int edgeTot,svTot,nxt[maxm],pre[maxm],head[maxn];
std::priority_queue<int, std::vector<int>, cmp> q; int read()
{
char ch = getchar();
int num = ;
bool fl = ;
for (; !isdigit(ch); ch = getchar())
if (ch=='-') fl = ;
for (; isdigit(ch); ch = getchar())
num = (num<<)+(num<<)+ch-;
if (fl) num = -num;
return num;
}
void addedge(int u, int v)
{
int c = read();
edges[++edgeTot] = Edge(v, c), nxt[edgeTot] = head[u], head[u] = edgeTot;
edges[++edgeTot] = Edge(u, c), nxt[edgeTot] = head[v], head[v] = edgeTot;
}
int get(int x){return fa[x]==x?x:fa[x]=get(fa[x]);}
int main()
{
memset(dis, 0x3f3f3f3f, sizeof dis);
memset(head, -, sizeof head);
n = read(), m = read();
for (int i=; i<=n; i++) fa[i] = i;
for (int i=; i<=m; i++) addedge(read(), read());
dis[] = , q.push();
while (q.size())
{
int tt = q.top();
q.pop();
for (int i=head[tt]; i!=-; i=nxt[i])
if (dis[edges[i].y] > dis[tt]+edges[i].val){
dis[edges[i].y] = dis[tt]+edges[i].val;
dep[edges[i].y] = dep[tt]+, pre[edges[i].y] = i, fat[edges[i].y] = tt;
q.push(edges[i].y);
}
}
for (int i=; i<=n; i++) treeTag[pre[i]] = ;
for (int i=; i<=edgeTot; i+=)
if (!treeTag[i]&&!treeTag[i+]){
int u = edges[i].y, v = edges[i+].y;
edgeSv[++svTot] = EdgeSv(u, v, edges[i].val+dis[u]+dis[v]);
}
std::sort(edgeSv+, edgeSv+svTot+);
for (int i=; i<=svTot; i++)
{
int u = edgeSv[i].x, v = edgeSv[i].y, lstu = , lstv = ;
int topu = get(u), topv = get(v);
while (topu!=topv)
{
if (dep[topu] < dep[topv])
std::swap(u, v), std::swap(lstu, lstv), std::swap(topu, topv);
if (!tag[u]){
tag[u] = i;
if (lstu) fa[lstu] = u;
}else if (lstu) fa[lstu] = topu;
lstu = topu, u = fat[topu], topu = get(u);
}
}
for (int i=; i<=n; i++)
if (!tag[i]) puts("-1");
else printf("%d\n",edgeSv[tag[i]].dis-dis[i]);
return ;
}
END
【思维题 并查集 图论】bzoj1576: [Usaco2009 Jan]安全路经Travel的更多相关文章
- BZOJ1576: [Usaco2009 Jan]安全路经Travel(最短路 并查集)
题意 给你一张无向图,保证从1号点到每个点的最短路唯一.对于每个点求出删掉号点到它的最短路上的最后一条边(就是这条路径上与他自己相连的那条边)后1号点到它的最短路的长度 Sol emmm,考场上想了个 ...
- [BZOJ1576] [Usaco2009 Jan]安全路经Travel(堆优化dijk + (并查集 || 树剖))
传送门 蒟蒻我原本还想着跑两边spfa,发现不行,就gg了. 首先这道题卡spfa,所以需要用堆优化的dijkstra求出最短路径 因为题目中说了,保证最短路径有且只有一条,所以可以通过dfs求出最短 ...
- BZOJ1576: [Usaco2009 Jan]安全路经Travel(树链剖分)
Description Input * 第一行: 两个空格分开的数, N和M * 第2..M+1行: 三个空格分开的数a_i, b_i,和t_i Output * 第1..N-1行: 第i行包含一个数 ...
- BZOJ1576 [Usaco2009 Jan]安全路经Travel
首先用Dijkstra做出最短路生成树,设dis[p]为1到p点的最短路长度 对于一条不在生成树上的边u -> v,不妨设fa为u.v的lca 则一fa到v的路径上的任意点x都可以由u达到,走的 ...
- 【BZOJ1576】[Usaco2009 Jan]安全路经Travel 最短路+并查集
[BZOJ1576][Usaco2009 Jan]安全路经Travel Description Input * 第一行: 两个空格分开的数, N和M * 第2..M+1行: 三个空格分开的数a_i, ...
- bzoj 1576: [Usaco2009 Jan]安全路经Travel 树链剖分
1576: [Usaco2009 Jan]安全路经Travel Time Limit: 10 Sec Memory Limit: 64 MB Submit: 665 Solved: 227[Sub ...
- BZOJ.1576.[Usaco2009 Jan]安全路经Travel(树形DP 并查集)
题目链接 BZOJ 洛谷 先求最短路树.考虑每一条非树边(u,v,len),设w=LCA(u,v),这条边会对w->v上的点x(x!=w)有dis[u]+dis[v]-dis[x]+len的距离 ...
- bzoj 1576: [Usaco2009 Jan]安全路经Travel——并查集+dijkstra
Description Input * 第一行: 两个空格分开的数, N和M * 第2..M+1行: 三个空格分开的数a_i, b_i,和t_i Output * 第1..N-1行: 第i行包含一个数 ...
- 【BZOJ】1576 [Usaco2009 Jan]安全路经Travel
[算法]最短路树+(树链剖分+线段树)||最短路树+并查集 [题解] 两种方法的思想是一样的,首先题目限制了最短路树唯一. 那么建出最短路树后,就是询问对于每个点断掉父边后重新找路径的最小值,其它路径 ...
随机推荐
- [WebShow系列] 倒计时展示相关问题
WebShow内置了倒计时功能. 后台参数维护: 倒计时参数说明: 倒计时基准时间设置(秒数):假设设置为90,也就是从1分30秒开始倒计时,同时有开始提示音. 倒计时提示1剩余秒数:假设设置为30, ...
- 管理docker容器
如果在容器中启动sshd,存在开销和攻击面增大的问题.同时也违反了Docker所倡导的一个容器一个进程的原则. docker attach 37d61466c69e \\注意:如果在stdin中exi ...
- Count the string (KMP+DP)
题目链接 #include <bits/stdc++.h> using namespace std; typedef long long ll; inline int read() { , ...
- 页面出现滚动条时,body里面的内容不能自动居中?
弹窗后允许页面滚动 这种方式通常使用 position: absolute; ,可以看看我做的这个 Demo.主要用来应对弹窗内容很大很多的情况,超过了屏幕的宽高需要产生滚动条来方便浏览者查看.有一些 ...
- Unity 打包PC和安卓的路径注意事项
if UNITY_STANDALONE_WIN || UNITY_EDITOR return Application.persistentDataPath + "/LocalData&quo ...
- java中存储金额
很早之前, 记得一次面试, 面试官问存储金钱用什么数据类型? 当时只知道8种数据类型(boolean, byte, short, int, long, float, double, char)的我, ...
- (转)Inode详解
Inode详解 原文:http://www.cnblogs.com/adforce//p/3522433.html 一.inode是什么 理解inode,要从文件储存说起. 文件储存在硬盘上,硬盘的 ...
- Zeppelin的入门使用系列之使用Zeppelin运行shell命令(二)
不多说,直接上干货! 前期博客 Zeppelin的入门使用系列之创建新的Notebook(一) 接下来,我将以ml-100k数据集,示范如何使用Spark SQL进行数据分析与数据可视化 因为 [ha ...
- JSON.stringify 语法讲解
作用:这个函数的作用主要是为了系列化对象的. 可能有些人对系列化这个词过敏,我的理解很简单.就是说把原来是对象的类型转换成字符串类型(或者更确切的说是json类型的).就这么简单.打个比方说,你有一个 ...
- Linux学习笔记——如何使用echo指令向文件写入内容
0.前言 本文总结如何使用echo命令向文件中写入内容,例如使用echo指令覆盖文件内容,使用echo指令向文件追加内容,使用echo指令往文件中追加制表符. echo向文件中输出内容 ...