【USACO06NOV】路障Roadblocks(Dijkstra)

原题见洛谷:题目

分析

 直接用一个dis表示最短路,dis2表示次短路。更新有以下几种:

1,dis[j]>dis[i]+w(i,j),直接更新dis[j]并把j入队。

2,dis2[j]>dis[i]+w(i,j),更新dis2[j]并把j入队。注意:此题要求严格小于最短路,所以还需要dis[j]>dis[i]+w(i,j)成立。

3,dis2[j]>dis2[i]+w(i,j),更新dis2[j]并把j入队。

以上三种只取一种。

注意这里的Dij不需要done数组,因为done只是标记最短路更新,但次短路可能还会更新。

#include<bits/stdc++.h>
using namespace std;
const int MAXN=5005;
const int MAXM=100005;
const int INF=400000000;
int N,M,np=0,last[MAXN],dis[MAXN],dis2[MAXN];
struct edge{int to,w,pre;}E[MAXM*2];
struct data
{
	int id,d;
	friend bool operator < (data a,data b) {a.d>b.d;}
};

char c;
void scan(int &x)
{
	for(c=getchar();c<'0'||c>'9';c=getchar());
	for(x=0;c>='0'&&c<='9';c=getchar()) x=x*10+c-'0';
}

void addedge(int u,int v,int w)
{
	E[++np]=(edge){v,w,last[u]};
	last[u]=np;
}

void dij()
{
	priority_queue<data>pq;
	for(int i=1;i<=N;i++) dis[i]=dis2[i]=INF;
	dis[1]=0; pq.push((data){1,0});
	while(!pq.empty())
	{
		data t=pq.top(); pq.pop(); int i=t.id;
		for(int p=last[i];p;p=E[p].pre)
		{
			int j=E[p].to,w=E[p].w;
			if(dis[j]>dis[i]+w)
			{
				dis[j]=dis[i]+w;
				pq.push((data){j,dis[j]});
			}
			else if(dis[j]<dis[i]+w&&dis2[j]>dis[i]+w)
			{
				dis2[j]=dis[i]+w;
				pq.push((data){j,dis[j]});
			}
			else if(dis2[j]>dis2[i]+w)
			{
				dis2[j]=dis2[i]+w;
				pq.push((data){j,dis[j]});
			}
		}
	}
}

int main()
{
	int i,u,v,w;
	scan(N);scan(M);
	for(i=1;i<=M;i++)
	{
		scan(u);scan(v);scan(w);
		addedge(u,v,w);
		addedge(v,u,w);
	} dij(); cout<<dis2[N]; return 0;
}

 

猜你喜欢

转载自blog.csdn.net/WWWengine/article/details/81750577
今日推荐