bzoj-1579: [Usaco2009 Feb]Revamping Trails 道路升级

1579: [Usaco2009 Feb]Revamping Trails 道路升级

Time Limit: 10 Sec  Memory Limit: 64 MB

Description

每天,农夫John需要经过一些道路去检查牛棚N里面的牛. 农场上有M(1<=M<=50,000)条双向泥土道路,编号为1..M. 道路i连接牛棚P1_i和P2_i (1 <= P1_i <= N; 1 <= P2_i<= N). John需要T_i (1 <= T_i <= 1,000,000)时间单位用道路i从P1_i走到P2_i或者从P2_i 走到P1_i 他想更新一些路经来减少每天花在路上的时间.具体地说,他想更新K (1 <= K <= 20)条路经,将它们所须时间减为0.帮助FJ选择哪些路经需要更新使得从1到N的时间尽量少.

Input

* 第一行: 三个空格分开的数: N, M, 和 K * 第2..M+1行: 第i+1行有三个空格分开的数:P1_i, P2_i, 和 T_i

Output

* 第一行: 更新最多K条路经后的最短路经长度.

Sample Input

4 4 1
1 2 10
2 4 10
1 3 1
3 4 100

Sample Output

1
HINT

K是1; 更新道路3->4使得从3到4的时间由100减少到0. 最新最短路经是1->3->4,总用时为1单位. N<=10000

Solution

用二维数组dis[i][j]表示1到i点用了j次道路升级后的最短路。

相当于建了一个分层图,除了第0层,每个点的dis值由上一层或所在的这一层更新而来,因为dijstra(很久都不会dijstra了,今天又去学了一下,觉得dijstra和SPFA的区别就是,dijstra用最小的dis去更新其它的dis,SPFA则不保证)每次找到最小的dis去更新其它的dis,所以第一次到达n号节点找到的就是最短路。

看到别人的题解里说SPFA要麻烦一点,需要跑k次,我不知道为什么SPFA不能像dijstra一样用二维的呐。

#include<algorithm>
#include<iostream>
#include<cstring>         //
#include<cstdlib>
#include<cstdio>
#include<queue>
#define nn 10010
#define mm 100010
using namespace std;
int e=0,k;
int dis[nn][25],fir[nn],nxt[mm],to[mm],w[mm];
struct node{
	int x,k,d;
	bool operator<(const node&b)const{          //priority——queue需要重载小于号
		return d>b.d;
	}
};
priority_queue<node> q;
int read()
{
	int ans=0,f=1;char ch=getchar();
	while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
	while(isdigit(ch)) {ans=ans*10+ch-'0';ch=getchar();}
	return ans*f;
}
void add(int u,int v,int ww)
{
	nxt[++e]=fir[u];fir[u]=e;to[e]=v;w[e]=ww;
	nxt[++e]=fir[v];fir[v]=e;to[e]=u;w[e]=ww;
}
int dijstra(int n)
{
	memset(dis,127,sizeof(dis));
	q.push((node){1,0,0});
	dis[1][0]=0;
	while(!q.empty())
	{
		node o=q.top();q.pop();
		if(o.d!=dis[o.x][o.k])
		  continue;
		if(o.x==n) 
		  return o.d;
		for(int i=fir[o.x];i;i=nxt[i])
		{
			if(dis[to[i]][o.k]>dis[o.x][o.k]+w[i])
			{
				dis[to[i]][o.k]=dis[o.x][o.k]+w[i];
				q.push((node){to[i],o.k,dis[to[i]][o.k]});
			}
			if(o.k<k&&dis[to[i]][o.k+1]>dis[o.x][o.k])
			{
				dis[to[i]][o.k+1]=dis[o.x][o.k];
				q.push((node){to[i],o.k+1,dis[to[i]][o.k+1]});
			}
		}
	}
}
int main()
{
	int n,m,u,v,ww;
	n=read();m=read();k=read();
	for(int i=1;i<=m;i++)
	{
		u=read();v=read();ww=read();
		add(u,v,ww);
	}
	printf("%d",dijstra(n));
	return 0;
}
原文地址:https://www.cnblogs.com/charlotte-o/p/7580189.html