bzoj3669: [Noi2014]魔法森林

1 篇文章 0 订阅
1 篇文章 0 订阅

题目链接
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);
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值