zoukankan      html  css  js  c++  java
  • 【BZOJ-1576】安全路径Travel Dijkstra + 并查集

    1576: [Usaco2009 Jan]安全路经Travel

    Time Limit: 10 Sec  Memory Limit: 64 MB
    Submit: 1044  Solved: 363
    [Submit][Status][Discuss]

    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

    Solution

    比较简单的一道题

    首先我们跑一遍最短路,得到最短路树,在松弛操作的时候加一句话即可

    然后我们发现对于不在最短路树上的边,如果把它加入树中,会形成一个环,它会影响这个环上除lca的其他点

    样例是这样的,黑边是指最短路树上的边,加入非树红边,影响的是红点,加入非树蓝边,有影响的是蓝点

    所发生的影响就是,环上点x,在加入边<u,v>会被更新成dis[u]+dis[v]+val<u,v>-dis[x]

    所以要求被更新后最小,就是要求dis[u]+dis[v]+val<u,v>最小,那么我们按照这个价值对非树边排序

    从权值小的开始更新。

    所以这样的话,中间会更新一些重复的,我们只要保证那些重复的不被更新即可,这个显然可以利用并查集维护一下

    这样时间复杂度大概是$O(nlogn+n×a(n))$

    Code

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<queue>
    using namespace std;
    int read()
    {
        int x=0,f=1; char ch=getchar();
        while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();}
        while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();}
        return x*f;
    }
    #define MAXN 100010
    #define MAXM 200010
    int N,M;
    struct EdgeNode{int next,to,t,from;}edge[MAXM<<1];
    int head[MAXN],cnt=1;
    void AddEdge(int u,int v,int w) {cnt++; edge[cnt].from=u; edge[cnt].next=head[u]; head[u]=cnt; edge[cnt].to=v; edge[cnt].t=w;}
    void InsertEdge(int u,int v,int w) {AddEdge(u,v,w); AddEdge(v,u,w);}
    #define Pa pair<int,int>
    #define INF 0x7fffffff
    priority_queue<Pa,vector<Pa>,greater<Pa> >q;
    int dis[MAXN],fa[MAXN];
    void Dijkstra(int S)
    {
        for (int i=1; i<=N; i++) dis[i]=INF;
        q.push(make_pair(0,S)); dis[S]=0;
        while (!q.empty())
            {
                int now=q.top().second;
                int Dis=q.top().first;
                q.pop();
                if (Dis>dis[now]) continue;
                for (int i=head[now]; i; i=edge[i].next)
                    if (Dis + edge[i].t < dis[edge[i].to])
                        dis[edge[i].to]=Dis+edge[i].t,
                        fa[edge[i].to]=now,
                        q.push(make_pair(dis[edge[i].to],edge[i].to));
            }
    }
    int f[MAXN];
    int F(int x) {if (!f[x]) return x; else return f[x]=F(f[x]);}
    struct RoadNode
    {    
        int u,v,t;
        bool operator < (const RoadNode & A) const
            {return t<A.t;}
    }road[MAXM];
    int tot,num;
    int ans[MAXN];
    void Add(RoadNode x)
    {
        int u=x.u,v=x.v,t=x.t;
        while (F(u)!=F(v))
            {
                num++;
                if (dis[F(u)]<dis[F(v)]) swap(u,v);
                ans[F(u)]=min(ans[F(u)],t-dis[F(u)]);
                u=f[F(u)]=fa[F(u)];
            }
    }
    int main()
    {
        N=read(),M=read();
        for (int x,y,z,i=1; i<=M; i++) x=read(),y=read(),z=read(),InsertEdge(x,y,z);
        Dijkstra(1);
        for (int i=2; i<=cnt; i+=2)
            {
                int u=edge[i].from,v=edge[i].to;
                if (fa[u]!=v && fa[v]!=u)
                    road[++tot].u=u,road[tot].v=v,road[tot].t=dis[u]+dis[v]+edge[i].t;
            }
        sort(road+1,road+tot+1);
    //    for (int i=1; i<=tot; i++)
    //        printf("%d %d %d
    ",road[i].u,road[i].v,road[i].t);
    //    for (int i=1; i<=N; i++) printf("%d  ",dis[i]); puts("");
        for (int i=1; i<=N; i++) ans[i]=INF;
        for (int i=1; i<=tot && num<N-1; i++) Add(road[i]);
        for (int i=2; i<=N; i++) printf("%d
    ",ans[i]==INF? -1:ans[i]);
        return 0;
    }

    写完就A了....

  • 相关阅读:
    集训队作业2018人类的本质
    推式子小技巧
    [Codeforces671D]Roads in Yusland
    线性规划的对偶问题
    数学虐哭空巢老人记
    Voronoi图与Delaunay三角剖分
    [ZJOI2018]保镖
    [SPOJ2939]Qtree5
    数据结构虐哭空巢老人记
    [CTSC2006]歌唱王国
  • 原文地址:https://www.cnblogs.com/DaD3zZ-Beyonder/p/5803248.html
Copyright © 2011-2022 走看看