您的位置:首页 > 其它

[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一遍,更新的就不需要更新啦

用并查集可以轻松实现

#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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  并查集