• 【洛谷P1119】灾后重建【Floyed最短路】


    在这里插入图片描述

    分析

    一开始的想法是在线SPFA,十五分钟敲完然后直接T掉4个点。。。

    只能说这道题Floyed真的巧妙。其实核心代码只有5行。
    这段代码的基本思想就是:最开始只允许经过1号顶点进行中转,接下来只允许经过1和2号顶点进行中转(第二次枚举的时候最短路已经是有1号点中转更新过的)……允许经过1~n号所有顶点进行中转,求任意两点之间的最短路程。用一句话概括就是:从 i i i号顶点到 j j j号顶点只经过前 k k k号点的最短路程。

    因为我们的最短路要求很多次,所以 k k k会经常从1开始,但是没有必要,只需要让用过的 k k k不再用(也就是前面更新过的保留到后面即可),这样子就不用更新没有用的最短路,从而达成优化。为什么可以呢?因为前面能用的点后面一定能用(时间递增),所以直接在前面的基础上更新就行。另外对于每个 k k k需要判断中转点是否重建完成。

    这样子跑的比SPFA快。

    上代码

    SPFA,60pts

    x#include<iostream>
    #include
    #include
    #include
    #include
    #pragma GCC optimize(2)
    using namespace std;
    
    struct node
    {
    	int to,next,w;
    }e[40010];
    
    int n,m,t[210],q,dis[210],v[210];
    int hd[40010],tot;
    
    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*10+c-'0',c=getchar();
        return x*f;
    }
    
    inline void add(int x,int y,int w)
    {
    	e[++tot]=(node){y,hd[x],w};
    	hd[x]=tot;
    }
    
    void spfa(int st,int lim)
    {
    	queue<int> q;
    	dis[st]=0;
    	v[st]=1;
    	q.push(st);
    	while(!q.empty())
    	{
    		int x=q.front();
    		q.pop();
    		v[x]=0;
    		for(int i=hd[x];i;i=e[i].next)
    		{
    			if(t[e[i].to]>lim) continue; 
    			if(dis[e[i].to]>dis[x]+e[i].w)
    			{
    				dis[e[i].to]=dis[x]+e[i].w;
    				if(!v[e[i].to])
    				{
    					q.push(e[i].to);
    					v[e[i].to]=1;
    				}
    			}
    		}
    	}
    }
    
    int main()
    {
    	n=read();m=read();
    	for(int i=1;i<=n;i++)
    	{
    		t[i]=read();
    	}
        for(int i=1;i<=m;i++)
        {
        	int x,y,w;
        	x=read();y=read();w=read();
        	x++,y++;
        	add(x,y,w);
        	add(y,x,w);
    	}
    	q=read();
    	while(q--)
    	{
    		memset(v,0,sizeof(v));
    		memset(dis,0x3f,sizeof(dis));
    		int x,y,z;
    		scanf("%d%d%d",&x,&y,&z);
    		x++,y++;
    		if(z<t[x]||z<t[y])
    		{
    			printf("-1\n");
    			continue;
    		}
    		spfa(x,z);
    		if(dis[y]==1061109567) printf("-1\n");
    		else printf("%d\n",dis[y]);
    	}
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92

    Floyed,100pts

    #include
    #include
    #include
    #include
    #include
    using namespace std;
    
    int n,m,t[210],q;
    int g[210][210],v[210];
    
    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*10+c-'0',c=getchar();
        return x*f;
    }
    
    int main()
    {
        memset(g,0x3f,sizeof(g));
    	n=read();m=read();
    	for(int i=1;i<=n;i++)
    	{
    		t[i]=read();
    		g[i][i]=0;
    	}
        for(int i=1;i<=m;i++)
        {
        	int x,y,w;
        	x=read();y=read();w=read();
        	x++,y++;
        	g[x][y]=g[y][x]=w;
    	}
    	
    	q=read();
    	while(q--)
    	{
    		int x,y,z;
    		scanf("%d%d%d",&x,&y,&z);
    		x++,y++;
    		for(int k=1;k<=n;k++)
    		{
    			if(t[k]<=z&&!v[k])
    			{
    				v[k]=1;
    				for(int i=1;i<=n;i++)
    				{
    					for(int j=1;j<=n;j++)
    					{
    						if(g[i][j]>g[i][k]+g[k][j])
    						{
    							g[i][j]=g[i][k]+g[k][j];
    						}
    					}
    				}
    			}
    		}
    		if(t[x]<=z&&t[y]<=z&&g[x][y]!=0x3f3f3f3f) cout<<g[x][y]<<endl;
    		else cout<<-1<<endl;
    	}
    	return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
  • 相关阅读:
    (1)bark-ml
    Websocket集群解决方案
    社区通过!Interim Grant Program提案详细内容(包含申请Grants链接)
    信息学奥赛一本通:1399:甲流病人初筛
    加速释放传统企业业务潜力,S2B2B商城建设方案引领电商模式新风向
    驾校教练爆笑语录
    有趣且重要的JS知识合集(17)矩形框交互算法
    C++ 原子操作与无锁编程
    客户案例 | 思腾合力助力深度图灵生成式AI应用平台建设
    驱动 私有数据传参点灯
  • 原文地址:https://blog.csdn.net/dglyr/article/details/126278223