栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

【题解】CF366D

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

【题解】CF366D

Description text{Description} Description

CF366D Dima and Trap Graph

在一张无向图上有 N N N 个点和 M M M 条边,每条边连接着点 a a a 和点 b b b,有无数个人编号为 1 , 2 , … , + ∞ 1,2,dots,+infty 1,2,…,+∞。通过某条边是要一定的条件的,对于每条边,有两个值 l l l 和 r r r,表示该条边只允许编号在 [ l , r ] [l,r] [l,r] 区间内的人通过,从 1 1 1 号点到达 N N N 号点,请求出最多有多少人可以通过,并求出这些人的编号(若有多组解取字典序最小的一组 )

  • 可能有重边和自环。
  • 如果没有人能通过只要输出 Nice work, Dima! 就可以了。
  • 对于 30 % 30% 30% 的数据, 1 ≤ N , M ≤ 10 1le N,Mle10 1≤N,M≤10;
  • 对于 100 % 100% 100% 的数据, 2 ≤ N ≤ 1000 , 0 ≤ M ≤ 3000 , 1 ≤ a , b ≤ N , 1 ≤ l ≤ r ≤ 1 0 6 2le Nle1000,0le Mle3000,1le a,ble N,1le lle rle10^6 2≤N≤1000,0≤M≤3000,1≤a,b≤N,1≤l≤r≤106。
Solution text{Solution} Solution

有两种思路(注意字典序最小的判断):

1. 1. 1. 最长路

遍历每一条边,对于第 i i i 条边,选取边权 ≥ l i ge l_i ≥li​ 的边,从 1 1 1 到 N N N 跑最长路,让 r r r 最大,在 l l l 固定的情况下,肯定是 r r r 越大越好。

时间复杂度 O ( M ⋅ M log ⁡ N ) = O ( M 2 log ⁡ N ) mathcal{O}(Mcdot Mlog N)=mathcal{O}(M^2log N) O(M⋅MlogN)=O(M2logN)。

2. 2. 2. 并查集

同样是遍历每一条边 i i i,将所有满足 l j ≤ l i l_jle l_i lj​≤li​ 的 j j j,都把 a j a_j aj​ 和 b j b_j bj​ 并入一个集合。

那么最终的 l l l 一定是 l i l_i li​,所以把所有的 r i r_i ri​ 取个 min ⁡ min min 作为最终的 r r r,当点 1 1 1 和点 N N N 在同一个集合内说明可以尝试去更新答案。

因为是并查集实现,结合路径压缩和按秩合并可以做到 O ( M 2 α ( N ) ) mathcal{O}(M^2alpha(N)) O(M2α(N)),不过因为 N ≤ 1000 Nle1000 N≤1000 所以优化不大,主要优化在于常数(

时间复杂度 O ( M 2 α ( N ) ) mathcal{O}(M^2alpha(N)) O(M2α(N))。

Code text{Code} Code 1. 1. 1.
#include 
#include 
#include 
#include 
using namespace std;

const int MAXN = 1005;
const int MAXM = 3005;
const int INF = 0x3f3f3f3f;

int cnt;
int head[MAXN];

struct edge
{
	int to, l, r, nxt;
}e[MAXM << 1];

void add(int u, int v, int l, int r)
{
	e[++cnt] = edge{v, l, r, head[u]};
	head[u] = cnt;
}

int dis[MAXN];
bool vis[MAXN];

struct node
{
	int u, r;
	bool operator <(const node &x)const
	{
		if (x.r == r)
		{
			return x.u < u;
		}
		return x.r > r;
	}
};

void init()
{
	memset(dis, -INF, sizeof(dis));
	memset(vis, false, sizeof(vis));
}

void dijkstra(int l)
{
	init();
	dis[1] = INF;
	priority_queue pq;
	pq.push(node{1, dis[1]});
	while (!pq.empty())
	{
		int u = pq.top().u;
		pq.pop();
		if (vis[u])
		{
			continue;
		}
		vis[u] = true;
		for (int i = head[u]; i; i = e[i].nxt)
		{
			if (e[i].l > l) //取在区间内的
			{
				continue;
			}
			int v = e[i].to;
			if (dis[v] < min(dis[u], e[i].r)) //r要取min
			{
				dis[v] = min(dis[u], e[i].r);
				pq.push(node{v, dis[v]});
			}
		}
	}
}

int l[MAXM], r[MAXM];

int main()
{
	int n, m;
	scanf("%d%d", &n, &m);
	for (int i = 1; i <= m; i++)
	{
		int u, v;
		scanf("%d%d%d%d", &u, &v, l + i, r + i);
		add(u, v, l[i], r[i]);
		add(v, u, l[i], r[i]);
	}
	int ansk = 0, ansl = 0, ansr = 0;
	for (int i = 1; i <= m; i++)
	{
		dijkstra(l[i]);
		int res = dis[n] - l[i] + 1;
		if (ansk < res || (ansk == res && ansl > l[i]))
		{
			ansk = res;
			ansl = l[i];
			ansr = dis[n];
		}
	}
	if (ansk)
	{
		printf("%dn", ansk);
		for (int i = ansl; i <= ansr; i++)
		{
			printf("%d ", i);
		}
	}
	else
	{
		puts("Nice work, Dima!");
	}
	return 0;
}
2. 2. 2.
#include 
#include 
#include 
using namespace std;

const int MAXN = 1005;
const int MAXM = 3005;
const int INF = 0x3f3f3f3f;

struct edge
{
	int u, v, l, r;
}e[MAXM];

bool cmp(edge x, edge y)
{
	if (x.r == y.r)
	{
		return x.l < y.l;
	}
	return x.r > y.r;
}

int n, m, r, ansk, ansl, ansr;
int fa[MAXN], siz[MAXN];

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

int find(int x)
{
	if (x == fa[x])
	{
		return x;
	}
	return fa[x] = find(fa[x]); //路径压缩
}

int main()
{
	scanf("%d%d", &n, &m);
	for (int i = 1; i <= m; i++)
	{
		scanf("%d%d%d%d", &e[i].u, &e[i].v, &e[i].l, &e[i].r);
	}
	sort(e + 1, e + m + 1, cmp);
	for (int i = 1; i <= m; i++)
	{
		init();
		r = INF;
		for (int j = 1; j <= m; j++)
		{
			if (e[j].l <= e[i].l)
			{
				int x = find(e[j].u), y = find(e[j].v);
				if (x != y)
				{
					if (siz[x] > siz[y]) //按秩合并
					{
						fa[y] = x;
						siz[x] += siz[y];
					}
					else
					{
						fa[x] = y;
						siz[y] += siz[x];
					}
					r = min(r, e[j].r);
					if (find(1) == find(n))
					{
						break;
					}
				}
			}
		}
		if (find(1) == find(n) && (ansk < r - e[i].l + 1 || (ansk == r - e[i].l + 1 && ansl > e[i].l)))
		{
			ansk = r - e[i].l + 1;
			ansl = e[i].l;
			ansr = r;
		}
	}
	if (ansk)
	{
		printf("%dn", ansk);
		for (int i = ansl; i <= ansr; i++)
		{
			printf("%d ", i);
		}
	}
	else
	{
		puts("0");
	}
	return 0;
}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/295961.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号