[BZOJ 1576]安全路经Travel
2016-03-16 08:08
337 查看
硬生生没看出来是所谓的次短路
OTZ http://cxjyxx.me/?p=662
对于一个最短路树。
一定有一些非树边(u, v)
对于任意一个非LCA的节点i
它的答案是每一个非树边对应的dis[u] + dis[v] + d(u, v) - dis[i]
然而dis[u] + dis[v] + d(u, v) 这个鬼和i无关
然后我们可以贪心啦
sort一遍,更新的就不需要更新啦
用并查集可以轻松实现
OTZ http://cxjyxx.me/?p=662
对于一个最短路树。
一定有一些非树边(u, v)
对于任意一个非LCA的节点i
它的答案是每一个非树边对应的dis[u] + dis[v] + d(u, v) - dis[i]
然而dis[u] + dis[v] + d(u, v) 这个鬼和i无关
然后我们可以贪心啦
sort一遍,更新的就不需要更新啦
用并查集可以轻松实现
#include #include #include #include #include #define maxn 500010 using namespace std; int n, m; struct Edge{int to, next, dis;}; Edge G[maxn], edge[maxn]; int h[maxn], cnt; void add(int u, int v, int d){ cnt ++; edge[cnt].to = v; edge[cnt].dis = d; edge[cnt].next = h[u]; h[u] = cnt; } priority_queue >Q; int dis[maxn], Count; bool vis[maxn << 1]; struct Edge_{ int u, v, d; bool operator<(const Edge_& k)const{ return dis[u] + dis[v] + d < dis[k.u] + dis[k.v] + k.d; } }test[maxn]; namespace Dijkstra{ int h[maxn], cnt = 1; void addG(int u, int v, int d){ cnt ++; G[cnt].to = v; G[cnt].dis = d; G[cnt].next = h[u]; h[u] = cnt; } void work(){ int u, v, d; for(int i = 1; i <= m; i ++){ scanf("%d%d%d", &u, &v, &d); addG(u, v, d), addG(v, u, d); } Q.push(make_pair(0, 1)); memset(dis, 0x7f, sizeof dis); dis[1] = 0; while(!Q.empty()){ int u = Q.top().second; Q.pop();if(vis[u])continue; vis[u] = true; for(int i = h[u]; i; i = G[i].next){ int v = G[i].to; if(vis[v])continue; if(dis[v] > dis[u] + G[i].dis){ dis[v] = dis[u] + G[i].dis; Q.push(make_pair(-dis[v], v)); } } } memset(vis, 0, sizeof vis); for(int i = 1; i <= n; i ++) for(int j = h[i]; j; j = G[j].next){ if(vis[j ^ 1])continue; int v = G[j].to; if(dis[v] == dis[i] + G[j].dis) add(i, v, G[j].dis); else if(dis[i] == dis[v] + G[j].dis) add(v, i, G[j].dis); else{ Count ++; test[Count].u = i; test[Count].v = v; test[Count].d = G[j].dis; }vis[j] = true; } sort(test + 1, test + 1 + Count); } } int fa[maxn], dep[maxn]; void dfs(int u){ dep[u] = dep[fa[u]] + 1; for(int i = h[u]; i; i = edge[i].next){ int v = edge[i].to; fa[v] = u; dfs(v); } } int par[maxn]; int getfa(int x){return x == par[x] ? x : par[x] = getfa(par[x]);} int ans[maxn]; void Union(int u, int v, int d){ int i = getfa(u), j = getfa(v); while(i != j){ if(dep[i] < dep[j]) swap(i, j); ans[i] = dis[u] + dis[v] + d - dis[i]; par[i] = fa[i]; i = getfa(i); } } int main(){ scanf("%d%d", &n, &m); Dijkstra::work(); for(int i = 1; i <= n; i ++) par[i] = i; dfs(1); memset(ans, -1, sizeof ans); for(int i = 1; i <= Count; i ++) Union(test[i].u, test[i].v, test[i].d); for(int i = 2; i <= n; i ++) if(~ans[i])printf("%d\n", ans[i]); else printf("-1\n"); return 0; }
相关文章推荐
- 1611:The Suspects
- HDU-1213-How Many Tables
- Longest Consecutive Sequence,Distinct Subsequences,Interleaving String,Scramble String
- 并查集_POJ 1182_食物链
- SARS病毒传染 并查集
- HDU 1213
- CSU1307 并查集+SPFA
- BestWiring——Kruskal算法&并查集
- 1611:The Suspects
- 并查集示例1
- 并查集(union-find)学习报告
- poj3728
- HDU-1233 还是畅通工程(最小生成树&并查集)
- Simon-【深入理解数据结构】有根树的不同实现① —— 并查集
- 家族
- poj 1417 True Liars 解题报告 并查集 DP
- poj 1161
- 并查集——HDOJ 1213How Many Tables解题报告
- 最小生成树——HDOJ 2988 Dark roads解题报告
- HDU 1198 Farm Irrigation(并查集)