http://hihocoder.com/problemset/problem/1139
这题提示上写的是二分,但是感觉不二分应该也可以,至少题目是AC的。。。
二分的思想就是二分答案的值,看能不能在k步内,得到这个答案值,可以采用bfs来判定。
不二分的话,就是需要一个dis[]数组来保存在前k步内,每个点的最小索敌值,因为bfs在往后的过程中step是越来越大的,所以前面能达到更小的,显然不会重复再跑大的,然后bfs的过程中更新即可。类似于spfa,但是没有对队列去重。
代码:
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <queue> #include <map> #include <set> #include <string> #include <vector> #define LL long long using namespace std; const int maxN = 100005; //链式前向星 struct Edge { int to, next; int val; }edge[maxN*2]; int head[maxN], cnt; void addEdge(int u, int v, int val) { edge[cnt].to = v; edge[cnt].next = head[u]; edge[cnt].val = val; head[u] = cnt; cnt++; } void initEdge() { memset(head, -1, sizeof(head)); cnt = 0; } int n, m, k, to; LL dis[maxN]; void input() { initEdge(); memset(dis, -1, sizeof(dis)); int u, v, t; for (int i = 0; i <= m; ++i) { scanf("%d%d%d", &u, &v, &t); addEdge(u, v, t); addEdge(v, u, t); } } inline LL myMax(LL x, LL y) { return x > y ? x : y; } struct Item { int index; LL val; int step; }; void work() { int u, v, t, step; LL val, len; Item p, tmp; queue<Item> q; dis[1]= 0; p.index = 1; p.step = 0; p.val = 0; q.push(p); while (!q.empty()) { p = q.front(); q.pop(); u = p.index; step = p.step; val = p.val; for (int i = head[u]; i != -1; i = edge[i].next) { v = edge[i].to; len = edge[i].val; if (dis[v] == -1 || myMax(val, len) < dis[v]) { dis[v] = myMax(val, len); p.index = v; p.step = step+1; p.val = dis[v]; if (p.step < k) q.push(p); } } } cout << dis[to] << endl; } int main() { //freopen("test.in", "r", stdin); //freopen("test.out", "w", stdout); while (scanf("%d%d%d%d", &n, &m, &k, &to) != EOF) { input(); work(); } return 0; }