WOJ#2423 安全出行Safe Travel

描述

  精灵最近在农场上泛滥,它们经常会阻止牛们从农庄(牛棚_1)走到别的牛棚(牛_i的目的 地是牛棚_i)。每一个精灵只认识牛_i并且知道牛_i一般走到牛棚_i的最短路经。所以它们在牛_i到牛棚_i之前的最后一条牛路上等牛_i。当然,牛不愿意遇到Gremlins,所以准备找 一条稍微不同的路经从牛棚_1走到牛棚_i。所以,请你为每一头牛_i找出避免精灵的最短路经的长度。

  和以往一样, 农场上的M (2 <= M <= 200,000)条双向牛路编号为1-M并且能让所有牛到 达它们的目的地, N(3 <= N <= 100,000)个编号为1-N的牛棚.牛路i连接牛棚a_i (1 <= a_i <= N)和b_i (1 <= b_i <= N)并且需要时间t_i (1 <=t_i <= 1,000)通过。没有两条牛路连接同样的牛棚,所有牛路满足a_i!=b_i.在所有数据中,牛_i使用的牛棚_1到牛 棚_i的最短路经是唯一的。

输入

  第一行: 两个空格分开的数, N和M

  第2-M+1行: 三个空格分开的数a_i, b_i,和t_i

输出

  第1-N-1行: 第i行包含一个数:从牛棚_1到牛棚_i+1并且避免从牛棚1到牛棚i+1最短路经上最后一条牛路的最少的时间。如果这样的路经不存在,输出-1。

题解

  智商不够,数据结构来凑。提供一个比较暴力的思路。

  先搞出最短路树。我们考虑加入一条非树边,两端点为u、v,权值为w,如果它会影响点x的答案,那么x的答案会变成d[u]+d[v]+w-d[x](d[x]为起点到x的最短路)。我们再考虑加入一条非树边会对哪些点产生影响:容易发现,会受影响的点是u到v的路径上出去lca的点。由于要使每个点的答案最小,所以这就是一个区间取min的问题,可以用树链剖分解决。放上代码:

#include<bits/stdc++.h>
using namespace std;
#define N 100010
#define INF 0x3f3f3f3f
int n,m;
int num=1,f[N],vst[N<<2];
struct node{
    int u,v,w,nxt;
}e[N<<2];
void add(int u,int v,int w){e[++num]=(node){u,v,w,f[u]};f[u]=num;}
//build graph
#define pii pair<int,int>
#define mp make_pair
int d[N],vis[N];
void dijkstra(){
    memset(d,0x3f,sizeof(d));
    priority_queue<pii,vector<pii>,greater<pii> > q;
    d[1]=0;q.push(mp(d[1],1));
    while(!q.empty()){
        pii t=q.top();q.pop();
        int dd=t.first,u=t.second;
        if(vis[u]) continue;vis[u]=1;
        for(int i=f[u];i;i=e[i].nxt){
            int v=e[i].v,w=e[i].w;
            if(d[v]>dd+w){d[v]=dd+w;q.push(mp(d[v],v));}
        }
    }
}
//shortest path
namespace TREE{
    int num,f[N];
    struct node{
        int u,v,nxt;
    }e[N<<1];
    void add(int u,int v){
        e[++num]=(node){u,v,f[u]};f[u]=num;
        e[++num]=(node){v,u,f[v]};f[v]=num;
    }
    //build graph
    #define lc (p<<1)
    #define rc (p<<1|1)
    struct tree{
        int l,r,mx;
    }t[N<<2];
    void up(int p){t[p].mx=max(t[lc].mx,t[rc].mx);}
    void now(int p,int v){t[p].mx=min(t[p].mx,v);}
    void down(int p){if(t[p].mx<INF) now(lc,t[p].mx),now(rc,t[p].mx);}
    void build(int p,int l,int r){
        t[p].l=l;t[p].r=r;
        if(l==r){t[p].mx=INF;return;}
        int mid=(l+r)>>1;
        build(lc,l,mid);build(rc,mid+1,r);up(p);
    }
    void update(int p,int l,int r,int v){
        if(v>=t[p].mx||l>r) return;
        if(l<=t[p].l&&t[p].r<=r){now(p,v);return;}
        int mid=(t[p].l+t[p].r)>>1;down(p);
        if(l<=mid) update(lc,l,r,v);
        if(r> mid) update(rc,l,r,v);
        up(p);
    }
    int query(int p,int k){
        if(t[p].l==t[p].r){return t[p].mx;}
        int mid=(t[p].l+t[p].r)>>1;down(p);
        if(k<=mid) return query(lc,k);
        else return query(rc,k);
    }
    //segment tree
    int cnt,dep[N],faz[N],seg[N],siz[N],son[N],top[N];
    void dfs1(int u,int fa,int d){
        dep[u]=d;faz[u]=fa;siz[u]=1;
        for(int i=f[u];i;i=e[i].nxt){
            int v=e[i].v;
            if(v==fa) continue;
            dfs1(v,u,d+1);siz[u]+=siz[v];
            if(siz[v]>siz[son[u]]) son[u]=v;
        }
    }
    void dfs2(int u,int st){
        seg[u]=++cnt;top[u]=st;
        if(!son[u]) return;dfs2(son[u],st);
        for(int i=f[u];i;i=e[i].nxt){
            int v=e[i].v;
            if(v==faz[u]||v==son[u]) continue;
            dfs2(v,v);
        }
    }
    void change(int x,int y,int v){
        int xx=top[x],yy=top[y];
        while(xx^yy){
            if(dep[xx]<dep[yy]){swap(xx,yy);swap(x,y);}
            update(1,seg[xx],seg[x],v);
            x=faz[xx];xx=top[x];
        }
        if(dep[x]>dep[y]) swap(x,y);
        update(1,seg[x]+1,seg[y],v);
    }
    //tree dissection
}
int main(){
    int x,y,z;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++){scanf("%d%d%d",&x,&y,&z);add(x,y,z);add(y,x,z);}
    dijkstra();
    for(int i=2;i<=num;i+=2){
        int u=e[i].u,v=e[i].v,w=e[i].w;
        if(d[u]+w==d[v]||d[v]+w==d[u]){TREE::add(u,v);vst[i]=vst[i^1]=1;}
    }
    TREE::dfs1(1,0,1);TREE::dfs2(1,1);TREE::build(1,1,n);
    for(int i=2;i<=num;i+=2){
        if(vst[i]) continue;
        int u=e[i].u,v=e[i].v,w=e[i].w,tmp=d[u]+d[v]+w;
        TREE::change(u,v,tmp);
    }
    for(int i=2;i<=n;i++){
        int ans=TREE::query(1,TREE::seg[i]);
        if(ans==INF) puts("-1");
        else printf("%d\n",ans-d[i]);
    }
    return 0;
}

原文地址:https://www.cnblogs.com/doyo2019/p/11708076.html

时间: 2024-11-07 10:37:15

WOJ#2423 安全出行Safe Travel的相关文章

[USACO09JAN]安全出行Safe Travel

[USACO09JAN]安全出行Safe Travel 题目描述 Gremlins have infested the farm. These nasty, ugly fairy-like creatures thwart the cows as each one walks from the barn (conveniently located at pasture_1) to the other fields, with cow_i traveling to from pasture_1 t

[USACO09JAN]安全出行Safe Travel(最短路径树)

传送门 求对于每个点删掉1到他的最短路上的最后一条边(就是这条路径上与他自己相连的那条边)后1到他的最短路的长度. 即:最短路径树:图中的源点到所有结点的最短路径构成的树. 最短路径树在dijkstra过程中就可以求出来,因为这个过程就相当于走一棵树. 然后就是选入杂边,对于一条杂边<u,v>,它加入后会形成一个环,这个环上所有的点除了lca都可以被这条杂边更新,即这些点删去它上面那条边后是可以走杂边的,但lca删去上面那条边后图就不连通了. 那么 disnew[x]=dis[u]+dis[v

9.8解题报告

9.8解题报告 前50min写完了三个题的暴力,但是暴力的正确性不高qwq. 没有造数据绝对不是因为我懒. 然后开始想正解,T1想了一个O(n)的方法,但是写代码的时候bug太多,所以调试花了将近2个小时. 然后剩下的两个题就没大看. 距考试结束还有20min时,总感觉自己的T1有bug,所以15min写完了n*√n的,交上了这个. 所以最后完美的炸掉了考试. T1 100    T2 20    T3 10 qwq浪费时间的人绝对不是我. T1 #include<cmath> #includ

Keeping the Network Safe!

1. Keeping the Network Safe 1.1 Network Device Security Measures After the hacker gains access to the network, four types of threats may arise: Information theft Identity theft Data loss/manipulation Disruption of service The four classes of physical

UVA 1048 - Low Cost Air Travel(最短路)

UVA 1048 - Low Cost Air Travel 题目链接 题意:给定一些联票,在给定一些行程,要求这些行程的最小代价 思路:最短路,一张联票对应几个城市就拆成多少条边,结点表示的是当前完成形成i,在城市j的状态,这样去进行最短路,注意这题有坑点,就是城市编号可能很大,所以进行各种hash 代码: #include <cstdio> #include <cstring> #include <vector> #include <queue> #in

UVA - 825Walking on the Safe Side(dp)

题目: UVA - 825Walking on the Safe Side(dp) 题目大意:给出一个n * m的矩阵,起点是1 * 1,终点是n * m,这个矩阵上有些点是不可以经过的,要求从起点到终点距离最短,并且不能走那种不能走的点,一共有多少种方式. 解题思路:要求路径最短的话,每个点要不向右走,要不向下走.dp[i][j] = dp[i][j + 1] + dp[i + 1][j]:当这个点不能通过,dp[i][j] = 0:这个坑点在样例输入,不一定是规范的输入,可能两个数字之间很多

Safe

GC safe-point (or safepoint) and safe-region Root referencesAn object is dead really means it is useless. Only the programmer knows if an object is useless or not. In order for the program to decide if an object is useless, we can use compiler analys

Travel(最短路)

Travel The country frog lives in has nn towns which are conveniently numbered by 1,2,…,n1,2,…,n. Among n(n−1)2n(n−1)2 pairs of towns, mm of them are connected by bidirectional highway, which needs aa minutes to travel. The other pairs are connected b

Warning: date(): It is not safe to rely on the system&#39;s timezone settings.

PHP调试的时候出现了警告: It is not safe to rely on the system解决方法,其实就是时区设置不正确造成的,本文提供了3种方法来解决这个问题. 实际上,从PHP 5.1.0开始当对使用date()等函数时,如果timezone设置不正确,在每一次调用时间函数时,都会产生E_NOTICE 或者 E_WARNING 信息,而又在php中,date.timezone这个选项,默认情况下是关闭的,无论用什么php命令都是格林威治标准时间,但是PHP5.3中如果没有设置部