zoukankan      html  css  js  c++  java
  • 【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;
    }
    
  • 相关阅读:
    软工写文档熟练使用word很重要——自动生成编号
    UML——类图
    软件开发模型
    UML基础(终极总结)
    想买一款笔记本戴尔的InspironTM 6400
    ASP.NET 2.0 Enter Key Default Submit Button
    使用.net备份和还原数据库
    GridView导出Excel研究
    使用c#建立虚拟目录
    OpacityMask
  • 原文地址:https://www.cnblogs.com/zyt1253679098/p/8867678.html
Copyright © 2011-2022 走看看