1576: [Usaco2009 Jan]安全路经Travel
Time Limit: 10 Sec Memory Limit: 64 MB Submit: 1448 Solved: 512 [Submit][Status][Discuss]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.
Sample Input
4 5
1 2 2
1 3 2
3 4 4
3 2 1
2 4 3
输入解释:
跟题中例子相同
1 2 2
1 3 2
3 4 4
3 2 1
2 4 3
输入解释:
跟题中例子相同
Sample Output
3
3
6
输出解释:
跟题中例子相同
3
6
输出解释:
跟题中例子相同
题目限制没有重边自环,且到每个点的最短路只有一条。。
dijkstra预处理(这题卡SPFA),建最短路树
对于一条无向边$(u, v)$,其长度为$w$
若其不在树上,那么考虑这条边的影响:对于$lca$到$v$的路径上所有点$t$都可以走$1,lca,u,v,t$
路径长度显然为$dis[u]+dis[v]+w-d[x]$
只要维护$dis[u]+dis[v]+w$最小值,树剖+线段树即可
#include <queue> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; char buf[10000000], *ptr = buf - 1; inline int readint(){ int n = 0; char ch = *++ptr; while(ch < '0' || ch > '9') ch = *++ptr; while(ch <= '9' && ch >= '0'){ n = (n << 1) + (n << 3) + ch - '0'; ch = *++ptr; } return n; } const int maxn = 100000 + 10, maxm = 200000 + 10, INF = 0x3f3f3f3f; int n, m; struct Edge{ int to, val, next; Edge(){} Edge(int _t, int _v, int _n): to(_t), val(_v), next(_n){} }e[maxm * 2]; int fir[maxn] = {0}, cnt = 0; inline void ins(int u, int v, int w){ e[++cnt] = Edge(v, w, fir[u]); fir[u] = cnt; e[++cnt] = Edge(u, w, fir[v]); fir[v] = cnt; } struct Node{ int id, dis; Node(){} Node(int _i, int _d): id(_i), dis(_d){} }tmp; class cmp{ public: bool operator () (const Node &a, const Node &b){ return a.dis > b.dis; } }; priority_queue<Node, vector<Node>, cmp> q; int dis[maxn], pre[maxn]; bool vis[maxn], mark[maxm * 2]; void dijkstra(){ for(int i = 1; i <= n; i++){ dis[i] = 0x3f3f3f3f; vis[i] = false; } dis[1] = 0; q.push(Node(1, 0)); int u, v; while(!q.empty()){ tmp = q.top(); q.pop(); u = tmp.id; if(vis[u]) continue; vis[u] = true; for(int i = fir[u]; i; i = e[i].next){ v = e[i].to; if(dis[v] > tmp.dis + e[i].val){ mark[pre[v]] = false; mark[i] = true; pre[v] = i; dis[v] = tmp.dis + e[i].val; q.push(Node(v, dis[v])); } } } } int fa[maxn], son[maxn], siz[maxn], dep[maxn]; void dfs1(int u){ son[u] = 0; siz[u] = 1; for(int v, i = fir[u]; i; i = e[i].next){ if(!mark[i]) continue; v = e[i].to; fa[v] = u; dep[v] = dep[u] + 1; dfs1(v); siz[u] += siz[v]; if(!son[u] || siz[v] > siz[son[u]]) son[u] = v; } } int top[maxn], ref[maxn], tcnt = 0; void dfs2(int u){ ref[u] = ++tcnt; if(!son[u]) return; top[son[u]] = top[u]; dfs2(son[u]); for(int v, i = fir[u]; i; i = e[i].next){ if(!mark[i]) continue; v = e[i].to; if(v == son[u]) continue; top[v] = v; dfs2(v); } } #define lson l, mid, rt << 1 #define rson mid + 1, r, rt << 1 | 1 int Min[maxn << 2], tag[maxn << 2]; void Build(int l, int r, int rt){ Min[rt] = tag[rt] = INF; if(l == r) return; else{ int mid = l + r >> 1; Build(lson); Build(rson); } } inline void PushDown(int rt){ if(tag[rt] == INF) return; Min[rt << 1] = min(Min[rt << 1], tag[rt]); Min[rt << 1 | 1] = min(Min[rt << 1 | 1], tag[rt]); tag[rt << 1] = min(tag[rt << 1], tag[rt]); tag[rt << 1 | 1] = min(tag[rt << 1 | 1], tag[rt]); tag[rt] = INF; } void Update(int ql, int qr, int val, int l, int r, int rt){ Min[rt] = min(Min[rt], val); if(ql <= l && r <= qr) tag[rt] = min(tag[rt], val); else{ PushDown(rt); int mid = l + r >> 1; if(ql <= mid) Update(ql, qr, val, lson); if(qr > mid) Update(ql, qr, val, rson); } } int Query(int qw, int l, int r, int rt){ if(l == r) return Min[rt]; else{ PushDown(rt); int mid = l + r >> 1; if(qw <= mid) return Query(qw, lson); else return Query(qw, rson); } } inline int Lca(int x, int y){ while(top[x] != top[y]){ if(dep[top[x]] < dep[top[y]]) swap(x, y); x = fa[top[x]]; } if(dep[x] > dep[y]) swap(x, y); return x; } inline void Change(int x, int f, int val){ while(top[x] != top[f]){ Update(ref[top[x]], ref[x], val, 1, n, 1); x = fa[top[x]]; } if(x != f) Update(ref[f] + 1, ref[x], val, 1, n, 1); } int a[maxm], b[maxm], t[maxm]; int main(){ fread(buf, sizeof(char), sizeof(buf), stdin); n = readint(); m = readint(); for(int i = 1; i <= m; i++){ a[i] = readint(); b[i] = readint(); t[i] = readint(); ins(a[i], b[i], t[i]); } dijkstra(); dfs1(1); dfs2(1); Build(1, n, 1); for(int lca, i = 1; i <= m; i++){ lca = Lca(a[i], b[i]); if(!mark[i * 2 - 1]) Change(b[i], lca, dis[a[i]] + dis[b[i]] + t[i]); if(!mark[i * 2]) Change(a[i], lca, dis[a[i]] + dis[b[i]] + t[i]); } for(int t, i = 2; i <= n; i++){ t = Query(ref[i], 1, n, 1); if(t != INF) printf("%d ", t - dis[i]); else puts("-1"); } return 0; };