zoukankan      html  css  js  c++  java
  • BZOJ3575: [Hnoi2014]道路堵塞

    BZOJ3575: [Hnoi2014]道路堵塞

    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的由交通部指定的最短路径上的道路的编号。
    2<N<100000,1<M<200000。所用道路长度大于0小于10000。

    Output

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

    Sample Input

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

    Sample Output

    6
    6

    HINT

    数据已加强By Vfleaking,另2017.9.1再加数据一组,未重测。


    题解Here!
    这个题自从2017.9.2的最后一个AC记录之后就没有人再AC了。。。
    包括我也是。。。
    这种无脑加强数据的题目基本上就是废题了。。。
    当然,还可以到洛谷/LOJ上去搞搞事:

    洛谷P3238 [HNOI2014]道路堵塞

    LOJ#2209. 「HNOI2014」道路堵塞

    $BZOJ$质量真心差。。。

    正题:

    首先我们不可能每次删掉当前边之后再跑一遍最短路。。。

    那么我们必须想办法优化我的删边+求得最短路过程。

    我们考虑删边之后,当前的从$1$到$n$的最短路只能是从$1$出发,在最短路径上走一段,再走一段非最短路,最后回到最短路径上。

    这个应该能理解。

    那么如果我们强制让$SPFA$不走当前边,在跑最短路的过程中,我只要发现走到了一个最短路径上的点上时,就可以用当前的距离更新一下$ans$。

    我们可以用堆存走到哪个点导致了更新$ans$。

    这样就可以在以后反复调用,保证全局最优了。

    但是!每次跑$SPFA$无需清空$dis$,因为从左往右做的时候,$dis$显然递减!

    想一想最短路的松弛操作就应该知道怎么回事了。

    不过,到达最短路上的点的标记必须清空!

    然后就可以跑了。。。

    附代码:

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<queue>
    #define MAXN 100010
    #define MAX ((1<<30)-1)
    using namespace std;
    int n,m,q;
    int top=0,stack[MAXN];
    int num[MAXN],t[MAXN],pos[MAXN],f[MAXN],g[MAXN];
    int head[MAXN],path[MAXN];
    bool vis[MAXN],used[MAXN];
    struct Graph{
    	int next,to,w;
    }a[MAXN<<1];
    struct node{
    	int x,dis;
    	bool operator <(const node &p)const{
    		return dis>p.dis;
    	}
    }b[MAXN];
    priority_queue<node> heap;
    inline int read(){
    	int date=0,w=1;char c=0;
    	while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();}
    	while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();}
    	return date*w;
    }
    inline int relax(int u,int v,int w){
    	if(path[v]>path[u]+w){
    		path[v]=path[u]+w;
    		return 1;
    	}
    	return 0;
    }
    inline void add(int u,int v,int w,int c){
    	a[c].to=v;a[c].w=w;a[c].next=head[u];head[u]=c++;
    }
    void spfa(int s,int w,int id,int time){
    	int u,v;
    	queue<int> que;
    	for(int i=1;i<=q+1;i++)used[i]=false;
    	path[s]=w;
    	vis[s]=true;
    	top=0;
    	que.push(s);
    	while(!que.empty()){
    		u=que.front();
    		que.pop();
    		vis[u]=false;
    		for(int i=head[u];i;i=a[i].next){
    			if(i==id)continue;
    			v=a[i].to;
    			if(pos[v]>time){
    				if(!used[pos[v]]){
    					used[pos[v]]=true;
    					stack[++top]=v;
    					b[v].x=pos[v];
    					b[v].dis=path[u]+a[i].w+g[pos[v]];
    				}
    				else b[v].dis=min(b[v].dis,path[u]+a[i].w+g[pos[v]]);
    			}
    			else{
    				if(relax(u,v,a[i].w)&&!vis[v]){
    					vis[v]=true;
    					que.push(v);
    				}
    			}
    		}
    	}
    	while(top)heap.push(b[stack[top--]]);
    }
    void work(){
    	for(int i=1;i<=q;i++){
    		spfa(t[i],f[i],num[i],i);
    		while(!heap.empty()&&heap.top().x<=i){
    			used[heap.top().x]=false;
    			heap.pop();
    		}
    		if(heap.empty())printf("-1
    ");
    		else printf("%d
    ",heap.top().dis);
    	}
    }
    void init(){
    	int u,v,w;
    	n=read();m=read();q=read();
    	for(int i=1;i<=n;i++){path[i]=MAX;vis[i]=false;}
    	for(int i=1;i<=m;i++){
    		u=read();v=read();w=read();
    		add(u,v,w,i);
    	}
    	t[1]=pos[1]=1;
    	for(int i=1;i<=q;i++){
    		num[i]=read();
    		t[i+1]=a[num[i]].to;
    		pos[a[num[i]].to]=i+1;
    	}
    	for(int i=1;i<=q;i++)f[i+1]=f[i]+a[num[i]].w;
    	for(int i=q;i>=1;i--)g[i]=g[i+1]+a[num[i]].w;
    }
    int main(){
    	init();
    	work();
        return 0;
    }

    $Update ext{于}2019.3.3$:

    好像现在在$BZOJ$上可以过了。

    但是复杂度有点玄学啊。。。

    算了,复杂度$O( ext{能过})$。。。

    过了就好。。。

    各位巨佬千万别像我这个菜鸡一样。。。

  • 相关阅读:
    array and ram
    char as int
    pointer of 2d array and address
    Install SAP HANA EXPRESS on Google Cloud Platform
    Ubuntu remount hard drive
    Compile OpenSSL with Visual Studio 2019
    Install Jupyter notebook and tensorflow on Ubuntu 18.04
    Build OpenCV text(OCR) module on windows with Visual Studio 2019
    Reinstall VirtualBox 6.0 on Ubuntu 18.04
    Pitfall in std::vector<cv::Mat>
  • 原文地址:https://www.cnblogs.com/Yangrui-Blog/p/9589270.html
Copyright © 2011-2022 走看看