TRAVEL

传送门

题目大意

给定一个 nn 个点和 mm 条边的无向图,每条边都有一个 [l,r][l,r] 的限制,请计算出从 11enen 的限制范围是多少(即路径上 ll 尽量小,rr 尽量大)。

100%100\% 的数据 2<=N<=1000,0<=M<=3000,1<=a,b<=N,1<=l<=r<=1062 <= N <= 1000, 0 <= M <= 3000, 1 <= a, b <= N, 1 <= l <= r <= 10^6

解题思路

考试时排序写错,惨丢 70pts70ptsrk 3rk \ 3

排序,然后枚举 ll,根据 ll 建边,用并查集判断是否联通,最后更新答案。

AC CODE

#include <bits/stdc++.h>
using namespace std;

#define int long long

#define _ 20005

int read()
{
	int x = 0;
	char c = getchar();
	while(c < '0' || c > '9') c = getchar();
	while(c >= '0' && c <= '9')
	{
		x = x * 10 + c - '0';
		c = getchar();
	}
	return x;
}

int mmax;

int n, m;

int ansk, ansl, ansr;

int fa[_ << 1];

int find(int x)
{
	return fa[x] == x ? x : fa[x] = find(fa[x]);
}

void init()
{
	for(int i = 1; i <= mmax; ++i) fa[i] = i;
}

struct abc
{
	int u, v, l, r;
} k[_ << 1];

bool cmp(abc a, abc b)
{
	if(a.r != b.r)
		return a.r > b.r;
	return a.l < b.l;
}

signed main()
{
	n = read(), m = read();
	for(int i = 1; i <= m; ++i)
	{
		k[i].u = read(), k[i].v = read(), k[i].l = read(), k[i].r = read();
		mmax = max(mmax, max(k[i].u, k[i].v));
	}
	sort(k + 1, k + m + 1, cmp);
	for(int i = 1; i <= m; ++i)
	{
		init();
		int r = INT_MAX;
		for(int j = 1; j <= m; ++j)
		{
			if(k[j].l <= k[i].l)
			{
				int uu = find(k[j].u), vv = find(k[j].v);
				if(uu != vv)
				{
					fa[vv] = uu;
					r = min(r, k[j].r);
					if(find(1) == find(n)) break;
				}
			}
		}
		if(find(1) == find(n) && (ansk < r - k[i].l + 1 || (ansk == r - k[i].l + 1 && ansl > k[i].l)))
		{
			ansk = r - k[i].l + 1;
			ansl = k[i].l;
			ansr = r;
		}
	}
	printf("%lld\n", ansk);
	if(ansk != 0)
		for(int i = ansl; i <= ansr; ++i)
			printf("%lld%c", i, " \n"[i == ansr]);
	return 0;
}
posted @ 2021-10-04 14:37  蒟蒻orz  阅读(2)  评论(0编辑  收藏  举报  来源