• 洛谷 [HNOI2014]道路堵塞 解题报告


    [HNOI2014]道路堵塞

    题意

    给一个有向图并给出一个这个图的一个(1sim n)最短路,求删去这条最短路上任何一条边后的最短路。


    又事SPFA玄学...

    有个结论,新的最短路一定是(1sim l,lsim r,rsim n)组成的,中间一段是非最短路,两边是原最短路

    先删去最短路

    然后从1开始枚举短边,按顺序维护(1sim i)(i)个点连到(rsim n)的最小值,发现我们要根据(r)的变换进行删除,可以拿一个堆维护。

    剩下的对每个点跑跑(SPFA)就可以了,每次注意删去不参与松弛的那条边。

    感性上是只跑了一次(SPFA)


    Code:

    #include <cstdio>
    #include <cstring>
    #include <queue>
    #include <cctype>
    int read()
    {
    	int x=0;char c=getchar();
    	while(!isdigit(c)) c=getchar();
    	while(isdigit(c)) x=x*10+c-'0',c=getchar();
    	return x;
    }
    const int N=2e5+10;
    int head[N],to[N],Next[N],edge[N],cnt;
    void add(int u,int v,int w)
    {
        to[++cnt]=v,edge[cnt]=w,Next[cnt]=head[u],head[u]=cnt;
    }
    struct node{int u,v,w;}E[N];
    int n,m,L,used[N],dis[N],disl[N],disr[N],num[N],ban[N],path[N],s[N],vis[N],tot;
    struct yuucute
    {
    	int v,w;
    	bool friend operator <(yuucute a,yuucute b){return a.w>b.w;}
    }yuu[N];
    std::priority_queue <yuucute> Q;
    void spfa(int ss,int ban,int tim)
    {
    	dis[ss]=disl[ss];
    	std::queue <int> q;
    	q.push(ss);
    	tot=0;
    	while(!q.empty())
    	{
    		int now=q.front();
    		q.pop();
    		used[now]=0;
    		for(int v,i=head[now];i;i=Next[i])
    			if(((v=to[i])!=ban||now!=ss)&&dis[v]>dis[now]+edge[i])
    			{
    				dis[v]=dis[now]+edge[i];
    				if(num[v]>tim){if(vis[v]!=tim) vis[s[++tot]=v]=tim;}
    				else if(!used[v]) {q.push(v);used[v]=1;}
    			}
    	}
    	while(tot)
    	{
    		int now=s[tot--];
    		if(!yuu[now].v||yuu[now].w>dis[now]+disr[now])
    		{
    			yuu[now].w=dis[now]+disr[now];
    			yuu[now].v=now;
    			Q.push(yuu[now]);
    		}
    	}
    }
    int main()
    {
    	n=read(),m=read(),L=read();
    	for(int i=1;i<=m;i++) E[i].u=read(),E[i].v=read(),E[i].w=read();
    	for(int i=1;i<=L;i++)
    	{
    		ban[path[i]=read()]=1;
    		num[E[path[i]].u]=i;
    		disl[E[path[i]].v]=disl[E[path[i]].u]+E[path[i]].w;
    	}
    	num[n]=L+1;
    	for(int i=L;i;i--) disr[E[path[i]].u]=disr[E[path[i]].v]+E[path[i]].w;
    	for(int i=1;i<=m;i++) if(!ban[i]) add(E[i].u,E[i].v,E[i].w);
    	memset(dis,0x3f,sizeof dis);
    	for(int i=1;i<=L;i++)
    	{
    		spfa(E[path[i]].u,E[path[i]].v,i);
    		while(!Q.empty()&&num[Q.top().v]<=i) Q.pop();
    		if(Q.empty()) puts("-1");
    		else printf("%d
    ",Q.top().w);
    	}
    	return 0;
    }
    

    2019.2.18

  • 相关阅读:
    【bzoj1616】[Usaco2008 Mar]Cow Travelling游荡的奶牛 bfs
    【bzoj1614】[Usaco2007 Jan]Telephone Lines架设电话线 二分+SPFA
    【bzoj1609】[Usaco2008 Feb]Eating Together麻烦的聚餐 dp
    【codevs1404】字符串匹配 KMP
    【bzoj4196】[Noi2015]软件包管理器 树链剖分+线段树
    【codevs3160】最长公共子串 后缀数组
    【bzoj4698】[Sdoi2008] Sandy的卡片 后缀数组
    【bzoj4278】[ONTAK2015]Tasowanie 贪心+后缀数组
    【bzoj1692】[Usaco2007 Dec]队列变换 贪心+后缀数组
    【bzoj1717】[Usaco2006 Dec]Milk Patterns 产奶的模式 后缀数组+离散化
  • 原文地址:https://www.cnblogs.com/butterflydew/p/10397591.html
Copyright © 2020-2023  润新知