时间限制 : 1000 MS 空间限制 : 65536 KB
问题描述
每天,农夫John需要经过一些道路去检查牛棚N<=10000里面的牛.
农场上有M(1<=M<=50,000)条双向泥土道路,编号为1~M. 道路i连接牛棚
和
(1 <=
<= N; 1 <=
<= N).
John需要
(1 <=
<= 1,000,000)时间单位用道路i从
走到
或者从
走到
他想更新一些路经来减少每天花在路上的时间.具体地说,他想更新K (1 <= K <= 20)条路经,将它们所须时间减为0.帮助FJ选择哪些路经需要更新使得从1到N的时间尽量少.
输入格式
- 第一行: 三个空格分开的数: N, M, 和 K
- 第2…M+1行: 第i+1行有三个空格分开的数:
输出格式
- 第一行: 更新最多K条路经后的最短路经长度.
样例输入
4 4 1
1 2 10
2 4 10
1 3 1
3 4 100
样例输出
1
提示
样例说明:
K是1; 更新道路3->4使得从3到4的时间由100减少到0. 最新最短路经是1->3->4,总用时为1单位.
才知道这叫做分层图。。大概就是多枚举了几个状态??
#include <bits/stdc++.h>
using namespace std;
inline int R(){
char t=getchar();int o=0;bool F=0;
while(t<48||t>57)F|=t==45,t=getchar();
for(;t<58&&t>47;t=getchar())o=(o<<1)+(o<<3)+t-48;
return F?-o:o;
}
const int N = 10005, M = 100005;
int Last[N], End[M], Next[M], Len[M], cnt_edge = 1;
int n, m, k;
struct node{
int v, x, cnt;
node(){};
node(int a,int b,int c){x=a;v=b;cnt=c;}
bool operator < ( const node &p ) const {
return v > p.v;
}
};
int dis[N][25];
inline void add_edge( int a, int b, int c ){
Len[++cnt_edge] = c;
End[cnt_edge] = b;
Next[cnt_edge] = Last[a];
Last[a] = cnt_edge;
}
priority_queue<node> q;
void dijkstra(){
dis[1][0] = 0;
q.push( node( 1, 0, 0 ) );
while( ! q.empty() ){
int cnt = q.top().cnt, x = q.top().x, v = q.top().v; q.pop();
for( int i = Last[x], y = End[i]; i; i = Next[i], y = End[i] ){
if( dis[y][cnt] > dis[x][cnt] + Len[i] ){
dis[y][cnt] = dis[x][cnt] + Len[i];
q.push( node( y, dis[y][cnt], cnt ) );
}
if( cnt < k && dis[y][cnt+1] > dis[x][cnt] ){
dis[y][cnt+1] = dis[x][cnt];
q.push( node( y, dis[y][cnt+1], cnt + 1 ) );
}
}
}
}
int main()
{
n = R(); m = R(); k = R();
int a, b, c;
for( int i = 1; i <= m; i ++ ){
a = R(); b = R(); c = R();
add_edge( a, b, c );
add_edge( b, a, c );
}
memset( dis, 120, sizeof( dis ) );
dijkstra();
cout << dis[n][k];
return 0;
}