http://poj.org/problem?id=3662
/* 题意:在一个农场里,要连接1到n的一条线路,现在有k条是免费的,剩下取最大值即为要付的钱, 现在给你一个农场图,要你求出最小的值,如果没有这个值输出-1 dp+优先队列 dp[i][j]表示到农场j用了i条免费线路所要发的钱 to表示与j连的下一个节点 dp[i][to] = min(max(dp[i][j],val), dp[i][to]); dp[i+1][to] = min(dp[i][j], dp[i+1][to]); */ #include<iostream> #include<algorithm> #include<queue> using namespace std; const int MAXN = 1005; const int MAXM = 20005; const int inf = 100000000; struct Edge { int v, w, next; }e[MAXM]; int head[MAXN], cnt; struct Node { int u, v, dist; bool operator<(const Node &a) const { return a.dist < dist; } Node(int u, int v, int dist):u(u),v(v),dist(dist){} }; priority_queue<Node> q; int dp[MAXN][MAXN]; int n, p, k; bool visit[MAXN][MAXN]; inline int max(int a, int b) { if(a>b) return a; else return b; } void addedge(int u, int v, int w)//建图 { e[cnt].v = v; e[cnt].w = w; e[cnt].next = head[u]; head[u] = cnt++; } int dij() { int i, j, temp, ans; for(i=0; i<=k; i++)//初始化 for(j=1; j<=n; j++) { dp[i][j] = inf; visit[i][j] = false; } dp[0][1] = 0;// while(!q.empty()) q.pop(); q.push(Node(0,1,0)); ans = -1; while(!q.empty()) { Node tmp = q.top();//每次都是选择最小的边进行扩展 q.pop(); if(tmp.v == n)//如果到终点了 { if(ans == -1 || dp[tmp.u][tmp.v] < ans) { ans = dp[tmp.u][tmp.v]; } } if(visit[tmp.u][tmp.v]) continue; visit[tmp.u][tmp.v] = true; for(i=head[tmp.v]; i!=-1; i=e[i].next) { int to = e[i].v; temp = max(dp[tmp.u][tmp.v], e[i].w); if(temp < dp[tmp.u][to]) { dp[tmp.u][to] = temp; q.push(Node(tmp.u, to, temp)); } if(tmp.u + 1 <= k && dp[tmp.u][tmp.v] < dp[tmp.u+1][to]) { dp[tmp.u+1][to] = dp[tmp.u][tmp.v]; q.push(Node(tmp.u+1, to, dp[tmp.u][tmp.v])); } } } return ans; } int main() { // freopen("in.txt", "r", stdin); int i, u, v, w; while(scanf("%d %d %d", &n, &p, &k) != EOF) { cnt = 1; memset(head, -1, sizeof(head)); for(i=0; i<p; i++) { scanf("%d %d %d", &u, &v, &w); addedge(u, v, w); addedge(v, u, w); } printf("%d/n", dij()); } return 0; }