题意:
给定一个n个点的无向图fr,to,w。
现在从1点到n点,有k条边可以免花费,求免费之后剩下的那些边里面最大花费最小的值是多少。
解析:
首先搞懂题意,从1点到n点可以有很多条路。
假设已经确定了一条路径,则这些边里面花费最大的k个肯定使用免费最赚,然后剩下边里面找到最大的就是当前的这个花费值了。
要使这个花费值最小,就直接假设到这个值去二分。
二分的比较项是大于当前这个花费值的边的条数,如何求这个条数?
将大于花费的边的值在求最短路里面搞成1,然后小于其的搞成0,然后求一个最短路就是条数了。
比较这个条数就能够确定当前花费值的取值过大或者过小了:
若当前条数小于k条,则说明大于花费的条数少了,说明花费值大了;
反之,花费小了。
然后二分的时候大概20次就行了,大了TLE,小了WA。
代码:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <stack>
#include <vector>
#include <queue>
#include <map>
#include <climits>
#include <cassert>
#define LL long long
using namespace std;
const int inf = 0x3f3f3f3f;
const double eps = 1e-8;
const double pi = 4 * atan(1.0);
const double ee = exp(1.0);
const int maxn = 1000 + 10;
int n, p, k;
vector< pair<int, int> > g[maxn];
int head[maxn];
bool vis[maxn];
int dis[maxn];
int eNum;
struct Edge
{
int fr, to, cost;
} e[maxn * maxn];
void addEdge(int fr, int to, int c)
{
e[eNum].fr = head[fr];
e[eNum].to = to;
e[eNum].cost = c;
head[fr] = eNum++;
}
void buildG(int val)
{
eNum = 0;
memset(head, -1, sizeof(head));
for (int u = 1; u <= n; u++)
{
int sz = g[u].size();
for (int i = 0; i < sz; i++)
{
int v = g[u][i].first;
int w = g[u][i].second;
if (val < w)
{
addEdge(u, v, 1);
addEdge(v, u, 1);
}
else
{
addEdge(u, v, 0);
addEdge(v, u, 0);
}
}
}
}
bool spfa(int val)
{
buildG(val);
for (int i = 1; i <= n; i++)
{
dis[i] = inf;
vis[i] = false;
}
stack<int> s;
s.push(1);
vis[1] = true;
dis[1] = 0;
while (!s.empty())
{
int cur = s.top();
s.pop();
for (int i = head[cur]; i != -1; i = e[i].fr)
{
int x = e[i].to;
if (dis[cur] + e[i].cost < dis[x])
{
dis[x] = dis[cur] + e[i].cost;
if (!vis[x])
{
vis[x] = true;
s.push(x);
}
}
}
vis[cur] = false;
}
// cout << dis[n] << endl;
return dis[n] <= k;
}
int main()
{
#ifdef LOCAL
freopen("in.txt", "r", stdin);
#endif // LOCAL
while (~scanf("%d%d%d", &n, &p, &k))
{
for (int i = 1; i <= n; i++)
g[i].clear();
int maxx = 0;
while (p--)
{
int fr, to, w;
scanf("%d%d%d", &fr, &to, &w);
g[fr].push_back(make_pair(to, w));
maxx = maxx < w ? w : maxx;
}
int lo = 0, hi = maxx;
for (int i = 0; i < 20; i++)
{
int mi = (lo + hi) >> 1;
if (spfa(mi))
hi = mi;
else
lo = mi;
}
if (hi == maxx)
puts("-1");
else
printf("%d\n", hi);
}
return 0;
}