BZOJ 3694 最短路

233333想简单了。。。。

题解参见http://hzwer.com/3710.html

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxv 4050
#define maxe 200500
#define inf 0x7f7f7f7f7f7f7f7fLL
using namespace std;
struct edge
{
    long long u,v,w,flag,nxt;
}e[maxe];
long long n,m,x,y,a,b,g[maxv],nume=0,dis[maxv];
long long top[maxv],fath[maxv],dfn[maxv],dep[maxv],size[maxv],son[maxv],times=0;
long long root,tot=0,ls[maxv<<2],rs[maxv<<2],lazy[maxv<<2];
void addedge(long long u,long long v,long long w,long long flag)
{
    e[++nume].u=u;
    e[nume].v=v;
    e[nume].w=w;
    e[nume].flag=flag;
    e[nume].nxt=g[u];
    g[u]=nume;
}
void dfs1(long long x)
{
    size[x]=1;son[x]=0;
    for (long long i=g[x];i;i=e[i].nxt)
    {
        long long v=e[i].v;
        if ((e[i].flag) && (v!=fath[x]))
        {
            fath[v]=x;dep[v]=dep[x]+1;dis[v]=dis[x]+e[i].w;
            dfs1(v);
            size[x]+=size[v];
            if (size[v]>size[son[x]]) son[x]=v;
        }
    }
}
void dfs2(long long x,long long father)
{
    dfn[x]=++times;top[x]=father;
    if (son[x]) dfs2(son[x],father);
    for (long long i=g[x];i;i=e[i].nxt)
    {
        long long v=e[i].v;
        if ((e[i].flag) && (v!=fath[x]) && (v!=son[x]))
            dfs2(v,v);
    }
}
void build(long long &now,long long left,long long right)
{
    now=++tot;lazy[now]=inf;
    if (left==right) return;
    long long mid=(left+right)>>1;
    build(ls[now],left,mid);
    build(rs[now],mid+1,right);
}
void modify(long long now,long long left,long long right,long long l,long long r,long long x)
{
    if ((left==l) && (right==r))
    {
        lazy[now]=min(lazy[now],x);
        return;
    }
    long long mid=(left+right)>>1;
    if (r<=mid) modify(ls[now],left,mid,l,r,x);
    else if (l>=mid+1) modify(rs[now],mid+1,right,l,r,x);
    else {modify(ls[now],left,mid,l,mid,x);modify(rs[now],mid+1,right,mid+1,r,x);}
}
long long lca(long long u,long long v)
{
    long long f1=top[u],f2=top[v];
    while (f1!=f2)
    {
        if (dep[f1]<dep[f2]) {swap(f1,f2);swap(u,v);}
        u=fath[f1];f1=top[u];
    }
    if (dep[u]<dep[v]) return u;
    else return v;
}
void work(long long x)
{
    long long u=e[x].u,v=e[x].v,ret=dis[u]+e[x].w+dis[v];
    long long t=lca(u,v);
    if (t==v) return;
    u=t;
    long long f1=top[u],f2=top[v];
    while (f1!=f2)
    {
        if (dep[f1]<dep[f2]) {swap(f1,f2);swap(u,v);}
        modify(root,1,n,dfn[f1],dfn[u],ret);
        u=fath[f1];f1=top[u];
    }
    if (u!=v)
    {
        if (dep[u]>dep[v]) swap(u,v);
        modify(root,1,n,dfn[u]+1,dfn[v],ret);
    }
}
long long ask(long long now,long long left,long long right,long long pos)
{
    if (left==right)
        return lazy[now];
    long long mid=(left+right)>>1;
    if (pos<=mid) return min(ask(ls[now],left,mid,pos),lazy[now]);
    else return min(ask(rs[now],mid+1,right,pos),lazy[now]);
}
int main()
{
    scanf("%lld%lld",&n,&m);
    for (long long i=1;i<=m;i++)
    {
        scanf("%lld%lld%lld%lld",&x,&y,&a,&b);
        addedge(x,y,a,b);
        addedge(y,x,a,b);
    }
    dfs1(1);
    dfs2(1,1);
    build(root,1,n);
    for (long long i=1;i<=nume;i++)
    {
        long long u=e[i].u,v=e[i].v,ret=dis[u]+e[i].w+dis[v];
        if (e[i].flag) continue;
        work(i);
    }
    for (long long i=2;i<=n;i++)
    {
        long long ret=ask(root,1,n,dfn[i]);
        if (ret==inf) printf("-1 ");
        else printf("%lld ",ret-dis[i]);
    }
    printf("\n");
    return 0;
}
时间: 2024-10-07 10:52:33

BZOJ 3694 最短路的相关文章

bzoj:3040: 最短路(road)

Description N个点,M条边的有向图,求点1到点N的最短路(保证存在).1<=N<=1000000,1<=M<=10000000 Input 第一行两个整数N.M,表示点数和边数.第二行六个整数T.rxa.rxc.rya.ryc.rp. 前T条边采用如下方式生成:1.初始化x=y=z=0.2.重复以下过程T次:x=(x*rxa+rxc)%rp;y=(y*rya+ryc)%rp;a=min(x%n+1,y%n+1);b=max(y%n+1,y%n+1);则有一条从a到b的,

BZOJ 3040: 最短路(road) ( 最短路 )

本来想学一下配对堆的...结果学着学着就偏了... 之前 kpm 写过这道题 , 前面的边不理它都能 AC .. 我也懒得去写前面的加边了... 用 C++ pb_ds 库里的 pairing_heap 水过去的... ---------------------------------------------------------------------- #include<cstdio> #include<cstring> #include<algorithm> #

BZOJ 2125 最短路 静态仙人掌

题目大意:给定一棵仙人掌,多次询问两点之间的最短路 静态仙人掌= = 在VFK讲仙人掌之前就想做= = 结果一直拖= = 好不容易写完了= = 刚过样例 BZ就开始维护- - 维护到闭营= = 交上去还WA了= = 尼玛我这傻逼到底还是把倍增LCA写挂了= = 算了回归正题 首先我们的思路是这样的 考虑给定的是一棵树 多次询问树上两点间距离 那么我们一般的做法是预处理每个点到根的距离 用两点到根距离之和减掉LCA到根距离的2倍 那么到了仙人掌上我们也可以套用这个做法 首先Tarjan处理出每个环

BZOJ 3040 最短路(road) 堆优化Dijkstra

题目大意:最短路. 思路:最短路. 贴一份比较高效的堆优化Dij模板吧. CODE: #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define _MAX 1000010 #define MAX 10000010 using namespace std; #define min(a,b) ((a) < (b) ? a:b) long long

BZOJ 2125 最短路 仙人掌最短路

为了证明我还活着所以我发了篇博客_ (:з」∠) _ 题意: 给定一张仙人掌图,n<=10000,多次询问两点间最短路. Q<=10000. 解析: 首先如果这是一棵树的话,那么我们只需要选定一个根,之后扫一遍这棵树,询问的话即是两点到根节点的距离之和减去二倍的两点lca到根节点距离. 那么如果是一棵仙人掌的话,我们强行套用这个办法,重新构造一棵树. 对于仙人掌中的一个环来说,我们把该环中深度最小的点当做这个环的根,然后环上其他点连向该环,非环上边正常连接. 这个树有什么优越性呢? 不妨假定1

BZOJ 2125: 最短路

2125: 最短路 Time Limit: 1 Sec  Memory Limit: 259 MBSubmit: 756  Solved: 331[Submit][Status][Discuss] Description 给一个N个点M条边的连通无向图,满足每条边最多属于一个环,有Q组询问,每次询问两点之间的最短路径. Input 输入的第一行包含三个整数,分别表示N和M和Q 下接M行,每行三个整数v,u,w表示一条无向边v-u,长度为w 最后Q行,每行两个整数v,u表示一组询问 Output

BZOJ 3040: 最短路(road) [Dijkstra + pb_ds]

3040: 最短路(road) Time Limit: 60 Sec  Memory Limit: 200 MBSubmit: 2476  Solved: 814[Submit][Status][Discuss] Description N个点,M条边的有向图,求点1到点N的最短路(保证存在).1<=N<=1000000,1<=M<=10000000 Input 第一行两个整数N.M,表示点数和边数.第二行六个整数T.rxa.rxc.rya.ryc.rp. 前T条边采用如下方式生成

BZOJ.2125.最短路(仙人掌 最短路Dijkstra)

题目链接 多次询问求仙人掌上两点间的最短路径. 如果是在树上,那么求LCA就可以了. 先做着,看看能不能把它弄成树. 把仙人掌看作一个图(实际上就是),求一遍根节点到每个点的最短路dis[i]. 对于u,v,若w=LCA(u,v)不在环上(u,v不同在一个环),那么dis(u,v)可以像在树上一样直接求得. 若w=u||w=v,(且w不是环内的一个点),dis(u,v)=dis[u/v]-dis[w]. 如果w在环上,那么设x,y为u,v往上能到的最近的环上的两个点,那么dis(u,v)=dis

bzoj 2125 最短路——仙人掌两点间最短路

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2125 因为看了TJ又抄了标程,现在感觉还是轻飘飘的--必须再做一遍. 两点间的情况: 1.直到 lca 都没有在一个环上的部分: 2.本来就处在一个环上: 3.本来不在一个环上,快到 lca 的时候开始处在一个环上了. 第一种情况就普通弄就行.处理倍增 lca 数组和根到每个点的最短路dis值. 第二种情况在环上两部分取较短的就行. 第三种情况是前两种的结合.需要找到 p 和 q 刚开始在