题目链接
https://lydsy.com/JudgeOnline/problem.php?id=3669
一条路径上有两个权值,这不好处理
最开始的想法是枚举bi,然后用kruskal求出路径最大ai
这显然会T飞
稍微想想就知道是关于bi的单峰函数,然后三分bi
一发拿了95分,开始思考人生……
仔细思考过后,这个函数有很多平的地方,如果mid在平的地方,我的三分写法就不知道该向哪里跳
mid = (l+r)>>1;
x = solve(mid-1);
y = solve(mid+1)
对bi打一波离散,基本每个点都是用的
还是挂,怎么办,让mid-1变成mid-2,更容易跳出平面(减太多会跳飞)
结束调(luan)参 (gao)
研究最短代码时发现spfa又快又短,wsl
#include <cstdio>
#include <algorithm>
using namespace std;
#define dd c=getchar()
int read() {int s=0,w=1;char c;while (dd,c>'9' || c<'0') if (c=='-') w=-1;while (c>='0' && c<='9') s=s*10+c-'0',dd;return s*w;}
#undef dd
void write(int x) {if (x<0) x=-x,putchar('-');if (x>=10) write(x/10);putchar(x%10|'0');}
void wln(int x) {write(x);puts("");}void wsp(int x) {write(x);putchar(' ');}
const int N = 1e5+7;
struct edge {
int u,t,a,b;
bool operator <(edge x) const {
return a < x.a;
}
}e[N];
int n,m;
int fa[N],ha[N];
int find(int x) {return x == fa[x] ? x : fa[x] = find(fa[x]);}
int solve(int V) {
for (int i = 1; i <= n; i++) fa[i] = i;
for (int i = 1; i <= m; i++) if (e[i].b <= V){
int u = find(e[i].u), v = find(e[i].t);
if (u != v) {
fa[u] = v;
if (find(1) == find(n)) return e[i].a;
}
}
return 1e9;
}
int main() {
// freopen("3669.in", "r", stdin);
// freopen("3669.out", "w", stdout);
n = read(); m = read();
for (int i = 1; i <= m; i++) {
e[i].u = read(); e[i].t = read(); e[i].a = read(); e[i].b = read();
ha[++*ha] = e[i].b;
}
sort(ha+1, ha+m+1);
*ha = unique(ha+1, ha+m+1) - ha - 1;
sort(e+1, e+m+1);
if (solve(1e5) == 1e9) return puts("-1"),0;
int l = 1, r = *ha;
while (l <= r) {
int mid = (l+r)>>1;
if (solve(ha[mid]) == 1e9) l = mid + 1;
else r = mid - 1;
}
r = *ha;
while (l < r - 1) {
int mid = (l+r)>>1, x = solve(ha[max(l,mid-2)]), y = solve(ha[min(r, mid+2)]);
if (x > y) l = mid;
else r = mid;
}
int ans = 1e9;
for (int i = l-5; i <= l+5; i++) ans = min(ans, ha[i] + solve(ha[i]));
wln(ans);
}