BZOJ1576 洛谷P2934 : [Usaco2009 Jan]安全路经Travel

95 篇文章 1 订阅
77 篇文章 0 订阅

1576: [Usaco2009 Jan]安全路经Travel

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
输入解释:
跟题中例子相同
Sample Output
3
3
6
输出解释:
跟题中例子相同
HINT
Source
Gold

这里写图片描述
inline:
这里写图片描述
非inline:
这里写图片描述

//啊哈哈哈哈 我的 树剖又回来了 inline似乎并没有什么软用  亲测
//有的确实变快了  有的却变慢了
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<queue>
using namespace std;
const int MAXN = 2e5+10 ;
const int MAXM = 4e5+10 ;
#define INF 0x3f3f3f3f
struct Edge{ int u,next,w,v;bool o; }e[MAXM];//边表
int head[MAXN],tot=1;
inline void Add_Edge(int u,int v,int w){
    e[++tot].u=u;e[tot].v=v;e[tot].w=w;
    e[tot].next=head[u];head[u]=tot;
}
typedef pair<int,int>Pair;
priority_queue<Pair,vector<Pair>,greater<Pair> >q;
int visx,vis[MAXN],dep[MAXN],dis[MAXN],siz[MAXN],son[MAXN],fa[MAXN],top[MAXN],n,m;
int p[MAXN],pos[MAXN],w[MAXN];
struct Tree{ int l,r,mn,tag,u; }tre[MAXN<<1];//线段树
inline void PushDown(int now){
    if(tre[now].tag==INF) return;
    int lc=now<<1,rc=now<<1|1;
    tre[lc].tag=min(tre[now].tag,tre[lc].tag);
    tre[rc].tag=min(tre[now].tag,tre[rc].tag);
    tre[lc].mn=min(tre[lc].mn,tre[now].tag);
    tre[rc].mn=min(tre[rc].mn,tre[now].tag);
}
inline void Dijkstra(){
    memset(dis,0x3f,sizeof dis );
    dis[1]=0;q.push(make_pair(0,1));
    while(!q.empty()){
        int u=q.top().second;q.pop();
        if(vis[u]) continue;vis[u]=1;
        for(int i=head[u];i;i=e[i].next){
            int v=e[i].v;
            if(dis[v]>dis[u]+e[i].w){
                dis[v]=dis[u]+e[i].w;
                e[i].o=1; e[p[v]].o=0; p[v]=i;
                q.push(make_pair(dis[v],v));
            }
        }
    }
}
inline void DFS_1(int u,int father,int deepth){
    siz[u]=1;dep[u]=deepth;fa[u]=father;
    for(int i=head[u];i;i=e[i].next){
        int v=e[i].v;
        if(v!=father&&e[i].o&&v!=son[u]){
            DFS_1(v,u,deepth+1);
            siz[u]+=siz[v];
            if(siz[son[u]]<siz[v]) son[u]=v;
        }
    }
}
inline void DFS_2(int u,int Top){
    top[u]=Top;w[pos[u]= ++visx]=u;
    if(son[u]) DFS_2(son[u],Top);
    for(int i=head[u];i;i=e[i].next){
        int v=e[i].v;
        if(e[i].o&&v!=fa[u]&&v!=son[u]) DFS_2(v,v);//
    }
}
inline void Built(int u,int l,int r){
    tre[u].l=l;tre[u].r=r;tre[u].mn=tre[u].tag=INF;
    if(l==r) return ;
    int mid=(l+r)>>1;
    Built(u<<1,l,mid);
    Built(u<<1|1,mid+1,r);
}
inline int Get_LCA(int u,int v){
    while(top[u]!=top[v]){
        if(dep[top[u]]<dep[top[v]]) swap(u,v);
        u=fa[top[u]];
    }
    if(dep[u]>dep[v]) swap(u,v);
    return u;
}
inline void UpDate(int u,int L,int R,int x){
    if(L==tre[u].l&&tre[u].r==R){
        tre[u].tag=min(tre[u].tag,x);
        if(L==R) tre[u].mn=min(x,tre[u].mn);
        return;
    }
    PushDown(u);
    int mid=(tre[u].l+tre[u].r)>>1;
    if(R<=mid) UpDate(u<<1,L,R,x);
    else if(L>mid) UpDate(u<<1|1,L,R,x);
    else UpDate(u<<1,L,mid,x),UpDate(u<<1|1,mid+1,R,x);
}
inline void modify(int x,int lca,int val){
    int fx=top[x];
    while(dep[fx]>dep[lca]){
        UpDate(1,pos[fx],pos[x],val);
        x=fa[fx],fx=top[x];
    }  
    if(x!=lca) UpDate(1,pos[lca]+1,pos[x],val);
}
inline int Query(int u,int x){
    if(tre[u].l==tre[u].r) return tre[u].mn;
    PushDown(u);
    int mid=(tre[u].l+tre[u].r)>>1;
    if(x<=mid) return Query(u<<1,x);
    else return Query(u<<1|1,x);

}
inline int read(){
    int x=0,f=1;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c-'0');c=getchar();}
    return x*f;
}
int main(){
    //scanf("%d%d",&n,&m);
    n=read();m=read();
    for(int u,v,w,i=1;i<=m;i++){
        u=read();v=read();w=read();
        //scanf("%d%d%d",&u,&v,&w);
        Add_Edge(u,v,w);Add_Edge(v,u,w);
    }
    Dijkstra();
    DFS_1(1,0,1);
    DFS_2(1,1);
    Built(1,1,visx);
    for(int i=1;i<=tot;i++){//双向边
        if(!e[i].o){
            int u=e[i].u,v=e[i].v,w=e[i].w;
            int LCA=Get_LCA(u,v);
            modify(v,LCA,dis[u]+dis[v]+e[i].w);
        }
    }
    for(int i=2;i<=n;i++){
        int x=Query(1,pos[i]);
        if(x==INF) puts("-1");
        else printf("%d\n",x-dis[i]);
    }
    return 0;
}
//不知为何 T的很惨  也许是我把题做难了
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<queue>
using namespace std;
const int MAXN = 2e5+10 ;
const int MAXM = 4e5+10 ;
const int INF = 1e9;
struct Edge{ int u,next,w,v;bool o; }e[MAXM];//边表
int head[MAXN],tot=1;
inline void Add_Edge(int u,int v,int w){
    e[++tot].u=u;e[tot].v=v;e[tot].w=w;
    e[tot].next=head[u];head[u]=tot;
}
struct Node{//堆优化的Dij
    int index,dis;
    bool operator < (const Node &a) const {
        return dis > a.dis;
    }
};
priority_queue<Node> q;
int visx,vis[MAXN],dep[MAXN],dis[MAXN],siz[MAXN],son[MAXN],fa

[MAXN],top[MAXN],n,m;
int p[MAXN],pos[MAXN];
struct Tree{
    int l,r,mn,tag,u;
    void minv(int x);
    void PushDown();
    void maintain();
}tre[MAXN<<1];//线段树
inline void Tree::minv(int x){ tag=x;mn=min(mn,x); }
inline void Tree::PushDown(){
    if(tag!=-1&&l!=r){
        tre[u<<1].minv(tag);
        tre[u<<1|1].minv(tag);
        tag=-1;
    }
}
inline void Tree::maintain(){
    if(l==r) return ;
    mn=min(tre[u<<1].mn,tre[u<<1|1].mn);
}
inline void Dijkstra(){
    for(int i=0;i<=n;i++) dis[i]=INF;
    dis[1]=0;q.push(Node{1,0});
    while(!q.empty()){
        int u=q.top().index;q.pop();
        if(vis[u]) continue;vis[u]=1;
        for(int i=head[u];i;i=e[i].next){
            int v=e[i].v;
            if(dis[v]>dis[u]+e[i].w){
                dis[v]=dis[u]+e[i].w;
                mark[p[v]]=0;mark[i]=1;p[v]=i;
                q.push(Node{v,dis[v]});
            }
        }
    }
}
inline void DFS_1(int u,int father,int deepth){
    siz[u]=1;dep[u]=deepth;fa[u]=father;son[u]=0;
    for(int i=head[u];i;i=e[i].next){
        if(mark[i]){
            int v=e[i].v;
            if(v!=father){
                DFS_1(v,u,deepth+1);
                siz[u]+=siz[v];
                if(siz[son[u]]<siz[v]) son[u]=v;
            }
        }
    }
}
inline void DFS_2(int u,int Top){
    top[u]=Top;pos[u]= ++visx;
    if(son[u]) DFS_2(son[u],Top);
    for(int i=head[u];i;i=e[i].next){
        int v=e[i].v;
        if(e[i].o&&v!=fa[u]&&v!=son[u]) DFS_2(v,v);//
    }
}
inline void Built(int u,int l,int r){
    tre[u].u=u;
    tre[u].l=l;tre[u].r=r;tre[u].mn=INF;tre[u].tag=-1;
    if(l==r) return ;
    int mid=(l+r)>>1;
    Built(u<<1,l,mid);
    Built(u<<1|1,mid+1,r);
}
inline int Get_LCA(int u,int v){
    while(top[u]!=top[v]){
        if(dep[top[u]]<dep[top[v]]) swap(u,v);
        u=fa[top[u]];
    }
    return dep[u]<dep[v] ? u : v;
}
inline void UpDate(int u,int L,int R,int x){
    tre[u].PushDown();
    if(L<=tre[u].l&&tre[u].r<=R) tre[u].minv(x);
    else {
        int mid=(tre[u].l+tre[u].r)>>1;
        if(L<=mid) UpDate(u<<1,L,R,x);
        if(mid<R) UpDate(u<<1|1,L,R,x);
        tre[u].maintain();
    }
}
inline int Query(int u,int x){
    tre[u].PushDown();
    if(tre[u].l==tre[u].r) return tre[u].mn;
    else {
        int mid=(tre[u].l+tre[u].r)>>1;
        if(x<=mid) return Query(u<<1,x);
        else return Query(u<<1|1,x);
    }
}
inline void Modify(int u,int v,int x){
    while(top[u]!=top[v]){
        if(dep[top[u]]<dep[top[v]]) swap(u,v);
        UpDate(1,pos[top[u]],pos[u],x);
        u=fa[top[u]];
    }
    if(dep[u]>dep[v]) swap(u,v);
    UpDate(1,pos[u],pos[v],x);
}
inline int read(){
    int x=0,f=1;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c-'0');c=getchar();}
    return x*f;
}
int main(){
    n=read();m=read();
    for(int u,v,w,i=1;i<=m;i++){
        u=read();v=read();w=read();
        Add_Edge(u,v,w);Add_Edge(v,u,w);
    }
    Dijkstra();
    DFS_1(1,0,1);
    DFS_2(1,1);
    Built(1,1,visx);
    for(int i=2;i<=tot;i+=2){//双向边
        int u=e[i].u,v=e[i].v,w=e[i].w;
        int LCA=Get_LCA(u,v);
        if(!mark[i]) Modify(v,LCA,dis[u]+dis[v]+e[i].w);
        if(!mark[i^1]) Modify(u,LCA,dis[u]+dis[v]+e[i].w);
    }
    for(int i=2;i<=n;i++){
        int w=Query(1,pos[i]);
        if(w==INF) printf("%d\n",-1);
        else printf("%d\n",w-dis[i]);
    }
    return 0;
}
//硬生生没看出是用并查集、、不过树剖+线段树有A的
//没时间了、、还要交作业
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#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){
    edge[++cnt].to=v;edge[cnt].dis=d;
    edge[cnt].next=h[u];h[u]=cnt;
}
priority_queue<pair<int, int> >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){
        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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

七情六欲·

学生党不容易~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值