【思维题 并查集 图论】bzoj1576: [Usaco2009 Jan]安全路经Travel
有趣的思考题
Description
.jpg)
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
[算法]最短路树+(树链剖分+线段树)||最短路树+并查集 [题解] 两种方法的思想是一样的,首先题目限制了最短路树唯一. 那么建出最短路树后,就是询问对于每个点断掉父边后重新找路径的最小值,其它路径 ...
随机推荐
- 整理的各种模板 (随时弃坑emmmmm)
线段树: #include<iostream> #include<cstdio> #include<algorithm> #include<cmath> ...
- Educational Codeforces Round 65 (Rated for Div. 2) D. Bicolored RBS
链接:https://codeforces.com/contest/1167/problem/D 题意: A string is called bracket sequence if it does ...
- HDU-1845-Jimmy's Assignment
链接:https://vjudge.net/problem/HDU-1845 题意: 给一个有向图,求最大匹配. 思路: 有相图的最大匹配,可以通过加上反向边, 求这个无向图的最大匹配, 原图的最大匹 ...
- php:比较两个txt文件,格式如下,分别取出a.txt有的b.txt没有的,b.txt有的a.txt没有的及两个都有的
<?php /*比较两个txt文件,格式如下,分别取出a.txt有的b.txt没有的,b.txt有的a.txt没有的及两个都有的 * a.txt: * A * B * C * D * b.txt ...
- eShopOnContainers(一)
微软微服务架构eShopOnContainers(一) 为了推广.Net Core,微软为我们提供了一个开源Demo-eShopOnContainers,这是一个使用Net Core框架开发的,跨平台 ...
- HDU 5883 F - The Best Path 欧拉通路 & 欧拉回路
给定一个图,要求选一个点作为起点,然后经过每条边一次,然后把访问过的点异或起来(访问一次就异或一次),然后求最大值. 首先为什么会有最大值这样的分类?就是因为你开始点选择不同,欧拉回路的结果不同,因为 ...
- java.lang.UnsupportedOperationException: setXIncludeAware is not supported on this JAXP implementation or earlier: class gnu.xml.dom.JAXPFactory的解决办法(图文详解)
不多说,直接上干货! 问题详情 java.lang.UnsupportedOperationException: setXIncludeAware is not supported on this J ...
- 学JS的书籍
1.JavaScript DOM 编程艺术 [说明] 这本书最大的特点就是简明易懂,循序渐进,适合初学者,非常容易上手. 计划:三天读完 读书总结:待写 2.Javascript权威指南 特点是权威. ...
- [总结] min-25筛
再不写总结我又会忘掉啊啊啊啊啊啊啊啊啊 这个\(min-25\)筛主要用来求一个积性函数的前缀和,就像这样\[\sum_{i=1}^n f(i)\] 不过这个积性函数要满足两个条件:质数\(p\)的函 ...
- Spoj REPEATS 后缀自动机+set
REPEATS - Repeats 链接:http://www.spoj.com/problems/REPEATS 题意:求S串中某个子串连续循环次数最多的次数. 想法: 从暴力开始,枚举所有串,求出 ...