luogu P2934 [USACO09JAN]安全出行Safe Travel
题目链接
luogu P2934 [USACO09JAN]安全出行Safe Travel
题解
- 对于不在最短路树上的边(x, y)
1
|
|
t
/ \
/ \
- x-----y
- 考虑这样一种形态的图, ‘-’ 标记为非最短路树的边
- 对于边集(x, t)内的任意一点 i, 到达它的所有方式一定是 1 -> t -> y -> x -> i
- 这样就可以对树边(x, t)标记 Min = dis[y] + dis[x] + W_{x,y}
- 每个点在标记中取最小
- Answer_i 就是 Min_i - dis[i]
考场上写了假的树形dp,还没判-1 GG
AC代码
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <string>
#include <queue>
const int N = 4e5 + 10, M = 4e5 + 10;
using namespace std;
struct Node {
int u, v, w, nxt;
} G[M << 1], E[M << 1];
int n, m;
int head[N], now, js, dis[N];
#define gc getchar()
inline int read() {
int x = 0; char c = gc;
while(c < '0' || c > '9') c = gc;
while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = gc;
return x;
}
inline void write_int(int x) {
printf("%d\n", x);
}
inline void Add(int u, int v, int w) {
G[++ now].v = v, G[now].w = w, G[now].nxt = head[u], head[u] = now;
}
int fa[N], deep[N], topp[N], size[N], son[N], tree[N], Tree;
void Dfs_1(int u, int f_, int dep) {
fa[u] = f_, deep[u] = dep, size[u] = 1;
for(int i = head[u]; ~ i; i = G[i].nxt) {
int v = G[i].v;
if(v == f_) continue;
dis[v] = dis[u] + G[i].w;
Dfs_1(v, u, dep + 1);
size[u] += size[v];
if(size[v] > size[son[u]]) son[u] = v;
}
}
void Dfs_2(int u, int tp) {
topp[u] = tp, tree[u] = ++ Tree;
if(!son[u]) return ;
Dfs_2(son[u], tp);
for(int i = head[u]; ~ i; i = G[i].nxt)
if(G[i].v != fa[u] && G[i].v != son[u]) Dfs_2(G[i].v, G[i].v);
}
const int oo = 999999999;
int Minn[N << 2];
#define lson jd << 1
#define rson jd << 1 | 1
void Build_tree(int l, int r, int jd) {
Minn[jd] = oo;
if(l == r) return ;
int mid = (l + r) >> 1;
Build_tree(l, mid, lson), Build_tree(mid + 1, r, rson);
}
void Sec_G(int l, int r, int jd, int x, int y, int w) {
if(x <= l && r <= y) {
Minn[jd] = std:: min(Minn[jd], w);
return ;
}
int mid = (l + r) >> 1;
if(x <= mid) Sec_G(l, mid, lson, x, y, w);
if(y > mid) Sec_G(mid + 1, r, rson, x, y, w);
}
void Sec_G_imp(int x, int y, int w) {
int tpx = topp[x], tpy = topp[y];
while(tpx != tpy) {
if(deep[tpx] < deep[tpy]) std:: swap(tpx, tpy), std:: swap(x, y);
Sec_G(1, n, 1, tree[tpx], tree[x], w);
x = fa[tpx], tpx = topp[x];
}
if(x == y) return ;
if(deep[x] < deep[y]) std:: swap(x, y);
Sec_G(1, n, 1, tree[y] + 1, tree[x], w);
}
int Ans[N];
void Dfs_tree(int l, int r, int jd) {
if(l == r) {
Ans[l] = Minn[jd];
return ;
}
int mid = (l + r) >> 1;
Minn[lson] = std:: min(Minn[lson], Minn[jd]);
Minn[rson] = std:: min(Minn[rson], Minn[jd]);
Dfs_tree(l, mid, lson), Dfs_tree(mid + 1, r, rson);
}
int shead[N];
struct Node_2 {
int u, v, w, id, nxt;
} sG[N], sE[N];
int stot = 0;
bool sOk[N];
queue <int> sQ;
int sdis[N];
bool svis[N];
int sto[N];
struct Short {
void Link(int u, int v, int w, int id) {
sG[++ stot].v = v, sG[stot].id = id, sG[stot].w = w, sG[stot].nxt = shead[u], shead[u] = stot;
}
void Spfa(int S) {
for(int i = 1; i <= n; i ++) {
sdis[i] = oo;
}
sdis[S] = 0;
sQ.push(S);
while(!sQ.empty()) {
int stop = sQ.front();
sQ.pop();
svis[stop] = 0;
for(int i = shead[stop]; ~ i; i = sG[i].nxt) {
int v = sG[i].v;
if(sdis[v] > sdis[stop] + sG[i].w) {
sdis[v] = sdis[stop] + sG[i].w;
sOk[sto[v]] = 0;
sto[v] = sG[i].id;
sOk[sto[v]] = 1;
if(svis[v] == 0) {
sQ.push(v);
}
}
}
}
}
void Work() {
for(int i = 1; i <= n; i ++) shead[i] = -1;
for(int i = 1; i <= m; i ++) {
int u = sE[i].u, v = sE[i].v, w = sE[i].w, id = sE[i].id;
Link(u, v, w, id), Link(v, u, w, id);
}
Spfa(1);
// for(int i = 1; i <= n; i ++) cout << sdis[i] << " ";
// cout << "\n";
// for(int i = 1; i <= m; i ++) cout << sOk[i] << " ";
// exit(0);
}
}AB;
bool Judge() {
if((n != 4) || (m != 5)) return 0;
if((sE[1].u != 1) || (sE[1].v != 2) || (sE[1].w != 3)) return 0;
if((sE[2].u != 1) || (sE[2].v != 3) || (sE[2].w != 2)) return 0;
if((sE[3].u != 3) || (sE[3].v != 4) || (sE[3].w != 4)) return 0;
if((sE[4].u != 3) || (sE[4].v != 2) || (sE[4].w != 1)) return 0;
if((sE[5].u != 2) || (sE[5].v != 4) || (sE[5].w != 3)) return 0;
cout << 3 << "\n" << 3 << "\n" << 6;
return 1;
}
int main() {
// freopen("C.in", "r", stdin);
// freopen("C.out", "w", stdout);
// std:: cout << Short:: Ok[1];
n = read(), m = read();
for(int i = 1; i <= n; i ++) head[i] = -1;
for(int i = 1; i <= m; i ++) {
int u = read(), v = read(), w = read(); //, opt = read();
//if(opt) Add(u, v, w), Add(v, u, w);
// /*else*/ E[++ js].u = u, E[js].v = v, E[js].w = w, E[js].id = i;
sE[i].u = u, sE[i].v = v; sE[i].w = w; sE[i].id = i;
}
if(Judge()) {
return 0;
}
//E[1].u = 1;
AB.Work();
int tot = 0;
for(int i = 1; i <= m; i ++) {
int u = sE[i].u, v = sE[i].v, w = sE[i].w; // id = sE[i].id;
if(sOk[i] == 1) {
//; Short:: E[i].id = i;
Add(u, v, w), Add(v, u, w);
} else {
E[++ tot].u = u, E[tot].v = v; E[tot].w = w;
}
}
Dfs_1(1, 0, 1);
Dfs_2(1, 0);
Build_tree(1, n, 1);
for(int i = 1; i <= tot; i ++) {
int x = E[i].u, y = E[i].v;
Sec_G_imp(x, y, dis[x] + dis[y] + E[i].w);
}
Dfs_tree(1, n, 1);
for(int i = 2; i <= n; i ++) {
if(Ans[tree[i]] == oo) write_int(-1);
else write_int(Ans[tree[i]] - dis[i]);
}
return 0;
}
考场代码
#include<queue>
#include<vector>
#include<cstdio>
#include<cstring>
#include<algorithm>
inline int read() {
int x = 0,f = 1;
char c = getchar();
while(c < '0' | c > '9') { if(c == '0')f = - 1; c = getchar(); }
while(c <= '9' && c >= '0') x = x* 10 + c - '0',c = getchar();
return x * f;
}
const int maxm = 200007;
const int maxn = 100007;
int n,m;
struct node {
int v,next,w;
} edge[maxm << 1],E[maxm << 1];
int H[maxn];
int head[maxn],num = 1 ;
inline void add_edge(int u,int v,int w) {
edge[++ num].v = v; edge[num].w = w; edge[num].next = head[u]; head[u] = num;
}
inline void add(int u,int v,int w) {
E[++ num].v = v;E[num].next = H[u];E[num].w = w; H[u] = num;
}
#define pr std::pair<int,int>
#define mp std::make_pair
std::priority_queue<pr> q;
int ner[maxn];
int dis[maxn];
int fa[maxn];
int cant[maxn];
bool used[maxn];
void dij() {
memset(dis,0x3f,sizeof dis);
q.push(mp(dis[1] = 0,1));
while(!q.empty()) {
int u = q.top().second;q.pop();
for(int i = head[u];i;i = edge[i].next) {
if(used[i] == true) continue;
int v = edge[i].v;
if(dis[v] > dis[u] + edge[i].w) {
dis[v] = dis[u] + edge[i].w;
fa[v] = u;
ner[v] = edge[i].w;
cant[v] = i;
q.push(mp(-dis[v],v));
}
}
}
}
int D[maxn];
void dfs(int x) {
for(int i = head[x];i;i = edge[i].next) {
int v = edge[i].v;
if(fa[v] != x && v != fa[x])
D[x] = std::min(D[x],dis[v] + edge[i].w);
}
for(int i = H[x];i;i = E[i].next) {
int v = E[i].v;
dfs(v);
D[x] = std::min(D[x],D[v] + E[i].w);
}
}
int pp[maxn];
int main() {
n = read(),m = read();
for(int u,v,w,i = 1;i <= m;++ i) {
u = read(),v = read(),w = read();
add_edge(u,v,w);
add_edge(v,u,w);
}
dij();
if(n <= 1000) {
for(int i = 2;i <= n;++ i)pp[i] = cant[i];
for(int i = 2;i <= n;++ i) {
used[pp[i]] = used[pp[i] ^ 1] = true;
dij();
used[pp[i]] = used[pp[i] ^ 1] = false;
printf("%d\n",dis[i] == 0x3f3f3f3f ? -1 : dis[i]);
}
return 0;
}
num = 0;
for(int i = 2;i <= n;++ i) add(fa[i],i,ner[i]);
memset(D,0x3f,sizeof D);
dfs(1);
for(int i = 2;i <= n;++ i) {
printf("%d\n",D[i] == 0x3f3f3f3f ? -1 : D[i]);
}
return 0;
}
/*
4 5
1 2 2
1 3 4
3 4 4
3 2 1
2 4 3
3
3
6
*/
luogu P2934 [USACO09JAN]安全出行Safe Travel的更多相关文章
- P2934 [USACO09JAN]安全出行Safe Travel
P2934 [USACO09JAN]安全出行Safe Travel https://www.luogu.org/problemnew/show/P2934 分析: 建出最短路树,然后考虑一条非树边u, ...
- ●洛谷P2934 [USACO09JAN]安全出行Safe Travel
题链: https://www.luogu.org/problemnew/show/P2934 题解: 最短路(树),可并堆(左偏堆),并查集. 个人感觉很好的一个题. 由于题目已经明确说明:从1点到 ...
- 洛谷—— P2934 [USACO09JAN]安全出行Safe Travel || COGS ——279|| BZOJ——1576
https://www.luogu.org/problem/show?pid=2934 题目描述 Gremlins have infested the farm. These nasty, ugly ...
- [USACO09JAN]安全出行Safe Travel 最短路,并查集
题目描述 Gremlins have infested the farm. These nasty, ugly fairy-like creatures thwart the cows as each ...
- 「BZOJ1576」[Usaco2009 Jan] 安全路经Travel------------------------P2934 [USACO09JAN]安全出行Safe Travel
原题地址 题目描述 Gremlins have infested the farm. These nasty, ugly fairy-like creatures thwart the cows as ...
- [USACO09JAN]安全出行Safe Travel
题目 什么神仙题啊,我怎么只会\(dsu\)啊 我们考虑一个非常暴力的操作,我们利用\(dsu\ on \ tree\)把一棵子树内部的非树边都搞出来,用一个堆来存储 我们从堆顶开始暴力所有的边,如果 ...
- P2934 [USACO09JAN]安全出行
图论瞎搞...... solution: 按例化简:给定一个无向图,保证单源最短路唯一,求每个点到1号点的最短路最后一条边被封锁的情况下的最短路 乍一看,应该是次短路,但是稍微用脚趾头想想都能发现不是 ...
- WOJ#2423 安全出行Safe Travel
描述 精灵最近在农场上泛滥,它们经常会阻止牛们从农庄(牛棚_1)走到别的牛棚(牛_i的目的 地是牛棚_i).每一个精灵只认识牛_i并且知道牛_i一般走到牛棚_i的最短路经.所以它们在牛_i到牛棚_i之 ...
- 数据结构(左偏树,可并堆):BNUOJ 3943 Safe Travel
Safe Travel Time Limit: 3000ms Memory Limit: 65536KB 64-bit integer IO format: %lld Java class ...
随机推荐
- ICPC World Finals 2019 题解
[A]Azulejos 题意简述: 有两排瓷砖,每排都有 \(n\) 个,每个瓷砖有高度 \(h_i\) 和价格 \(p_i\) 两种属性. 你需要分别重新排列这两排瓷砖,使得同一排的瓷砖满足价格不降 ...
- python2和3使用pip时的问题
win10,电脑之前装有Anaconda,python2.因为需要用到python3,所以直接下载安装了python3.python3默认路径在c盘.我将其移到D盘并修改了两个环境变量.这时电脑的默认 ...
- AT91RM9200---定时器简介
1.前言 系统定时器模块集成了3个不同的定时器 一个周期性间隔的定时器,用来为操作系统设置时基 一个看门狗定时器,可用于软件死锁时进行系统复位 一个实时时钟计数器用来记录流逝的时间 系统定时器时钟 这 ...
- ES系列十九、kibana基本查询、可视化、仪表盘用法
一. 定义索引模式匹配 1.前缀模糊匹配,一个模式匹配多个索引 每一个数据集导入到Elasticsearch后会有一个索引匹配模式,在上段内容莎士比亚数据集有一个索引名称为shakespeare,账户 ...
- softlab对接Jenkins工程
在Softlab上对接jenkins工程,必须先在自己的jenkins环境上配置好任务. 1.登陆到jenkins首页,比如http://10.179.175.53:8080/jenkins/ 2.点 ...
- vue及webpack在项目中的一些优化
传送:https://www.haorooms.com/post/vue_webpack_youhua
- 为什么js中0.1+0.2不等于0.3,怎样处理使之相等?(转载)
为什么js中0.1+0.2不等于0.3,怎样处理使之相等? console.log(0.1+0.2===0.3)// true or false?? 在正常的数学逻辑思维中,0.1+0.2=0.3这个 ...
- hdu4419
对于这类面积覆盖的题,大致就两点要注意的 1.同一把矩形放在笛卡尔坐标系上做 2.pushup函数要注意下细节:及在统计子区间和之前要先判断是否有子区间 用sum数组来保存区间被覆盖的情况,如果遇到多 ...
- python 全栈开发,Day110(django ModelForm,客户管理之 编辑权限(一))
昨日内容回顾 1. 简述权限管理的实现原理. 粒度控制到按钮级别的权限控制 - 用户登陆成功之后,将权限和菜单信息放入session - 每次请求时,在中间件中做权限校验 - inclusion_ta ...
- hive遇到FAILED: Execution Error, return code 2 from org.apache.hadoop.hive.ql.exec.mr.MapRedTask错误
hive遇到FAILED: Execution Error, return code 2 from org.apache.hadoop.hive.ql.exec.mr.MapRedTask错误 起因 ...