题解 CF366D Dima and Trap Graph
题意
给出一个 $n$ 个点,$m$ 条边的无向图,每条边有区间 $\left[l_i,r_i\right]$,求某条 $1$ 到 $n$ 路径组成的边集,使该边集中所有区间的交内的正整数元素个数最多。
$n\le10^3,m\le3\times10^3$
题解
萌萌题。
显然最后区间交的左右端点为某两条边的区间的左右端点。
当左端点固定时,右端点的取法是有单调性的,即比最大区间小的区间肯定可以全部到 $n$。
于是可以枚举每条边,当这条边的区间左端点即最终区间的左端点时,二分右端点的边,判断 $1$ 到 $n$ 是否连通即可。
判断联通并查集或直接搜都可以,但前者常数大概会小些,跑的快很多。
没啥细节,也挺好写。
复杂度即 $O(nm\log m)$。
#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;
}

浙公网安备 33010602011771号