题解 CF366D Dima and Trap Graph

link

题意

给出一个 n 个点,m 条边的无向图,每条边有区间 [li,ri],求某条 1n 路径组成的边集,使该边集中所有区间的交内的正整数元素个数最多。

n103,m3×103

题解

萌萌题。

显然最后区间交的左右端点为某两条边的区间的左右端点。

当左端点固定时,右端点的取法是有单调性的,即比最大区间小的区间肯定可以全部到 n

于是可以枚举每条边,当这条边的区间左端点即最终区间的左端点时,二分右端点的边,判断 1n 是否连通即可。

判断联通并查集或直接搜都可以,但前者常数大概会小些,跑的快很多。

没啥细节,也挺好写。

复杂度即 O(nmlogm)

#include <bits/stdc++.h>
using namespace std;
namespace IO {
    //read and write
} using namespace IO;
const int N = 1e3 + 10, M = 6e3 + 10;
int n, m, ans;
struct edge {
    int to, l, r, nxt;
} e[M];
int head[N], cnt;
vector<int> tmp;
bool vis[N];
void add(int u, int v, int l, int r) {
    e[++cnt] = (edge){v, l, r, head[u]};
    head[u] = cnt;
}
bool dfs(int u, int l, int r) {
    if(u == n) return 1;
    vis[u] = 1;
    for(int i = head[u], v; i; i = e[i].nxt) {
        v = e[i].to;
        if(vis[v] || e[i].l > l || e[i].r < r) continue;
        if(dfs(v, l, r)) return 1;
    }
    return 0;
}
int main() {
    n = read(), m = read();
    for(int i = 1, u, v, l, r; i <= m; i++) {
        u = read(), v = read(), l = read(), r = read();
        add(u, v, l, r), add(v, u, l, r), tmp.push_back(r);
    }
    sort(tmp.begin(), tmp.end());
    for(int i = 1; i <= m; i++) {
        int l = lower_bound(tmp.begin(), tmp.end(), e[i << 1].l) - tmp.begin(), r = m - 1, mid = l + r >> 1, res = -1;
        while(l <= r) {
            memset(vis, 0, sizeof(vis));
            mid = l + r >> 1;
            if(dfs(1, e[i << 1].l, tmp[mid])) res = mid, l = mid + 1;
            else r = mid - 1;
        }
        if(!~res) continue;
        ans = max(ans, tmp[res] - e[i << 1].l + 1);
    }
    if(!ans) printf("Nice work, Dima!");
    else printf("%d", ans);
    return 0;
}
posted @   Terac  阅读(7)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话
点击右上角即可分享
微信分享提示