• 【POJ3255/洛谷2865】[Usaco2006 Nov]路障Roadblocks(次短路)


    题目:

    POJ3255

    洛谷2865

    分析:

    这道题第一眼看上去有点懵……

    不过既然要求次短路,那估计跟最短路有点关系,所以就拿着优先队列优化的Dijkstra乱搞,搞着搞着就通了。

    开两个数组:(dis)存最短路,(dis2)存次短路

    在松弛的时候同时更新两个数组,要判断三个条件

    (u)是当前考虑的点,(v)是与(u)有边相连的点,(d(u,v))表示从(u)(v)的边长)

    1.如果(dis[v]>dis[u]+d(u,v)),则更新(dis[v])

    2018.11.09Updated: 同时(dis2[v])应成为原(dis[v])。原代码有误,已更新。

    2.如果(dis[v]<dis[u]+d(u,v))(不能取等,否则(dis2[v])(dis[v])可能相等)且(dis2[v]>dis[u]+d(u,v)),则更新(dis2[v])

    3.如果(dis2[v]>dis2[u]+d(u,v)),则更新(dis2[v])(显然,如果2成立,更新后(dis2[v]=dis[u]+d(u,v)<dis2[u]+d(u,v)),即3一定不成立)

    如果上述三个条件中有任意一个成立,则将(v)入队。

    还要注意一个地方:因为次短路可能会走“回头路” (即成环) ,所以一个点可以多次进队,不能使用(vis)数组判重。

    以及起点的(dis2)不能初始化为0,因为起点的次短路一定是沿着与其相连的最短的边走出去再回来。

    代码:

    #include<cstdio>
    #include<algorithm>
    #include<queue> 
    #include<cstring>
    #include<vector>
    using namespace std;
    int dis[5010],dis2[5010],n,m;
    struct point
    {
    	int id;
    	int dis;
    	bool operator<(const point &b)const
    	{
    		return dis>b.dis;
    	}
    };
    struct edge
    {
    	int to;
    	int w;
    };
    priority_queue<point>q;
    vector<edge>g[5010];
    int main(void)
    {
    	scanf("%d%d",&n,&m);
    	for(int i=0;i<m;i++)
    	{
    		int a,b,c;
    		scanf("%d%d%d",&a,&b,&c);
    		g[a].push_back((edge){b,c});
    		g[b].push_back((edge){a,c});
    	}
    	memset(dis,0x3f3f3f3f,sizeof(dis));
    	memset(dis2,0x3f3f3f3f,sizeof(dis2));
    	dis[1]=0;
    	q.push((point){1,0});
    	while(!q.empty())
    	{
    		int u=q.top().id,d=q.top().dis;
    		q.pop();
    		if(d>dis2[u])continue;
    		for(int i=0;i<g[u].size();i++)
    		{
    			int v=g[u][i].to,w=g[u][i].w;
    			bool flag=false;
    			if(dis[v]>dis[u]+w)
    			{
    				dis2[v]=dis[v];
    				dis[v]=dis[u]+w;flag=true;
    			}
    			if(dis[v]<dis[u]+w&&dis2[v]>dis[u]+w)
    				dis2[v]=dis[u]+w,flag=true;
    			
    			if(dis2[v]>dis2[u]+w)
    				dis2[v]=dis2[u]+w,flag=true;
    				
    			if(flag)q.push((point){v,dis[v]});
    		}
    	}
    	printf("%d",dis2[n]);
    	return 0;
    }
    
  • 相关阅读:
    nginx 简单应用
    js判断图片是否存在
    Quartz Cron 生成工具
    c# 读写文件时文件正由另一进程使用,因此该进程无法访问该文件
    SQL Server 将某一列的值拼接成字符串
    EF 里的 join and Group Join
    .net EF Join 关联表分页查询
    IIS 设置文件可下载
    windows 2003 无法安装 .net4.0 windows服务
    NEST 增删改查
  • 原文地址:https://www.cnblogs.com/zyt1253679098/p/8867678.html
Copyright © 2020-2023  润新知