1. 程式人生 > >bzoj1579: [Usaco2009 Feb]Revamping Trails 道路升級

bzoj1579: [Usaco2009 Feb]Revamping Trails 道路升級

cpp 它的 digi ostream 不知道 分開 sam using char

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;
}

bzoj1579: [Usaco2009 Feb]Revamping Trails 道路升級