• BZOJ 3575 道路堵塞


    Description

    A国有N座城市,依次标为1到N。同时,在这N座城市间有M条单向道路,每条道路的长度是一个正整数。现在,A国交通部指定了一条从城市1到城市N的路径,并且保证这条路径的长度是所有从城市1到城市N的路径中最短的。不幸的是,因为从城市1到城市N旅行的人越来越多,这条由交通部指定的路径经常发生堵塞。现在A国想知道,这条路径中的任意一条道路无法通行时,由城市1到N的最短路径长度是多少。

    Input

        输入文件第一行是三个用空格分开的正整数N、M和L,分别表示城市数目、单向道路数目和交通部指定的最短路径包含多少条道路。
        按下来M行,每行三个用空格分开的整数a、b和c,表示存在一条由城市a到城市b的长度为c的单向道路。这M行的行号也是对应道路的编号,即其中第1行对应的道路编号为1,第2行对应的道路编号为2,…,第M行对应的道路编号为M。最后一行为L个用空格分开的整数sp(1)…,,sp(L),依次表示从城市1到城市N的由交通部指定的最短路径上的道路的编号。

    Output

        输出文件包含L行,每行为一个整数,第i行(i=1,2…,,L)的整数表示删去编号为sp(i)的道路后从城市1到城市N的最短路径长度。如果去掉后没有从城市1到城市N的路径,则输出一1。

    Sample Input


    6 6 4
    1 2 1
    2 3 1
    4 6 1
    2 5 2
    5 4 3
    1 2 3 4

    Sample Output

    -1
    7
    7
    -1


    HINT

      100%的数据满足2<N<100000,1<M<200000。所用道路长度大于0小于10000。

    这题我用的ydc的做法。。。但是不得不承认他还是太屌了。。。QAQ

    首先很容易想到即使去掉一条边之后,最短路依然是pre[a]+suf[b]+dis(a,b),其中a,b均为最短路上的点,pre指a到起点的最短路距离,b为b到终点的最短路距离,dis(a,b)为a到b的距离(不走最短路上的边)。。。

    然后我就想到这里了。。。

    之后就是ydc神奇做法。首先肯定还是枚举删去的边,然后从这条边的出发点开始跑spfa,不走删掉的边(注意,不要取清空dis数组,因为每个点的dis肯定是单调递减的,不然必然会TLE)。从该点跑到另一个最短路上的点p(p必须在所删的边之后),然后把整条路径的长度和p一起加入平衡树中。出来平衡树中取出长度最小的边,若其做对应的p点(最短路)并没有在所删的边之后,该边删除。若平衡树为空,则输出-1。

    不得不说这个做法很漂亮,它利用到了枚举边的单调性,反正我肯定想不到。。。。

    如果实在是不懂的话,看代码,代码应该很好理解。

     1 #include<set>
     2 #include<queue>
     3 #include<cstring>
     4 #include<cstdio>
     5 #include<cstdlib>
     6 using namespace std;
     7 
     8 #define maxn (200010)
     9 int side[maxn],toit[maxn],next[maxn],dis[maxn],pos[maxn],occ[maxn],stack[maxn];
    10 int pre[maxn],suf[maxn],len[maxn],n,m,l,id,cnt,p[maxn],edge[maxn],val[maxn];
    11 bool ban[maxn],in[maxn];
    12 struct node
    13 {
    14     int to,val;
    15     friend inline bool operator <(const node &a,const node &b)
    16     {
    17         if (a.val != b.val) return a.val < b.val;
    18         else return pos[a.to] < pos[b.to]; 
    19     }
    20 };
    21 multiset <node> MS;
    22 
    23 inline int read()
    24 {
    25     int x=0,f=1;char ch=getchar();
    26     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    27     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    28     return x*f;
    29 }
    30 
    31 inline void add(int a,int b,int c)
    32 {
    33     next[++cnt] = side[a]; side[a] = cnt;
    34     toit[cnt] = b; len[cnt] = c;
    35 }
    36 
    37 inline void spfa(int d,int source,int lim)
    38 { 
    39     queue <int> team; int top = 0; 
    40     team.push(source); dis[source] = d; ++id;
    41     while (!team.empty())
    42     {
    43         int now = team.front(); team.pop();
    44         for (int i = side[now];i;i = next[i])
    45         {
    46             if (ban[i]) continue;
    47             if (pos[toit[i]] >= lim)
    48             {
    49                 if (occ[toit[i]] != id)
    50                     occ[toit[i]] = id,stack[++top] = toit[i],val[toit[i]] = dis[now]+len[i]+suf[pos[toit[i]]];
    51                 else val[toit[i]] = min(val[toit[i]],dis[now]+len[i]+suf[pos[toit[i]]]);
    52             }
    53             else if (dis[toit[i]] > dis[now]+len[i])
    54             {
    55                 dis[toit[i]] = dis[now] + len[i];
    56                 if (!in[toit[i]]) in[toit[i]] = true,team.push(toit[i]);
    57             }
    58         }
    59         in[now] = false;
    60     }
    61     for (int i = 1;i <= top;++i) MS.insert((node) {stack[i],val[stack[i]]});
    62 }
    63 
    64 inline void work()
    65 {
    66     pos[1] = p[1] = 1;
    67     for (int i = 1;i <= l;++i)
    68         edge[i] = read(),pos[toit[edge[i]]] = i+1,p[i+1] = toit[edge[i]];
    69     for (int i = 1;i <= l;++i) pre[i] = pre[i-1]+len[edge[i]];
    70     for (int i = l;i;--i) suf[i] = suf[i+1]+len[edge[i]];
    71     memset(dis,0x7,4*(n+5)); dis[1] = 0;
    72     for (int i = 1;i <= l;++i)
    73     {
    74         ban[edge[i]] = true; spfa(pre[i-1],p[i],i+1); ban[edge[i]] = false;
    75         while (!MS.empty()&&pos[MS.begin()->to]<=i) MS.erase(MS.begin());
    76         if (MS.empty()) puts("-1");
    77         else printf("%d
    ",MS.begin()->val);
    78     }
    79 }
    80 
    81 int main()
    82 {
    83     freopen("3575.in","r",stdin);
    84     freopen("3575.out","w",stdout);
    85     n = read(),m = read(),l = read(); int a,b,c; 
    86     while (m--) a = read(),b = read(),c = read(),add(a,b,c);
    87     work();
    88     fclose(stdin); fclose(stdout);
    89     return 0;
    90 }
    View Code
  • 相关阅读:
    EOJ 1822 Hanoi Tower IV
    Firefox,chrome,IE上传图片预览
    js保存,获取,删除cookie的操作
    jquery 特效
    SimpleDateFormat转换时间,12,24时间格式[转]
    javascript捕获页面窗口关闭事件
    [转]ajQuery的deferred对象详解
    iframe
    火狐路径问题
    JAVA折腾微信公众平台(Token验证)[转]
  • 原文地址:https://www.cnblogs.com/mmlz/p/4297696.html
Copyright © 2020-2023  润新知