CF366D Dima and Trap Graph Problem Solution

meaning of the title

Given a sheet with nn nodes,mmundirected graph of m edges (possibly with cycles or multiple edges), for each node iii , yesli l_iliSum ri r_iri, defined after passing through the node, can only be carried in li l_iliSum ri r_irinumbers in between.

Start from the node numbered 1 (which initially carries all natural numbers), and arrive at the node numbered nnFor n nodes, find the node that can carry the most at the end.

If the number of nodes is the same, output the group with the smallest lexicographical order.

If the number of nodes is 0, output Nice work, Dima!.

answer

A question from a mock competition.

Dichotomous + graph.

Dichotomous nature:

Find a critical point on the number line, that is, the left side of the point can satisfy the condition, but the right side cannot satisfy the condition (or the left side cannot, the right side can).

In this problem, the value of r is monotonic . That is, there is a critical point, so that the smaller r value cannot be satisfied, and the larger r value can be satisfied.

However, l is not monotonic . For example, it can be satisfied when the value of l is 1, and it can be satisfied when the value of l is 5, but whether it can be satisfied when the value of l is 3 cannot be directly determined.

Therefore, the value of r can be obtained by bisection, and the value of l can only be obtained by enumeration.

The above is the idea.

But when implementing, we can use the union search optimization:

We enumerate the values ​​of l from small to large, and on this basis, we enumerate each edge by the value of r from large to small.

Guaranteed ei.l e_i.l for each edge usedei. The value of l is smaller than the value of l of the current enumeration.

This is where the idea of ​​dichotomy comes into play.

Every time an edge is used, it is maintained by a union search, if f 1 = fn f_1 = f_nf1=fn, just record the answer, and finally output the best answer.

code

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

#define rint register int
const int inf = 1e6 + 5, maxn = 1005;
int n, m;
int cnt, hd[maxn];
struct node{
    
    
	int s, t;
	int l, r;
}e[maxn * 4];
int f[maxn];
int ansl, num;
int recl[maxn * 4];

inline int read ()
{
    
    
	int x = 1, s = 0;
	char ch = getchar ();
	while (ch < '0' or ch > '9'){
    
    if (ch == '-') x = -1; ch = getchar ();}
	while (ch >= '0' and ch <= '9') s = s * 10 + ch - '0', ch = getchar ();
	return x * s;
}

inline bool cmp (node a, node b)
{
    
    
	return a.r == b.r ? a.l < b.l : a.r > b.r;
}

inline void init ()
{
    
    
	for (rint i (1); i <= n; ++i) f[i] = i;
}

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

int main ()
{
    
    
	n = read (), m = read ();
	for (rint i (1); i <= m; ++i) e[i].s = read (), e[i].t = read (), e[i].l = read (), e[i].r = read (), recl[i] = e[i].l;
	sort (e + 1, e + m + 1, cmp);
	sort (recl + 1, recl + m + 1);
	for (rint i (1); i <= m; ++i)
	{
    
    
		init ();
		bool flag = 0;
		int tl = recl[i], tr = inf;
		for (rint j (1); j <= m; ++j)
		{
    
    
			if (e[j].l > tl) continue;
			int u = find (e[j].s), v = find (e[j].t);
			if (u != v)
			{
    
    
				f[u] = v;
				tr = min (tr, e[j].r);
				if (find (1) == find (n)) 
				{
    
    
					flag = 1;
					break;
				}
			}
		}
		if (flag and num < tr - tl + 1) ansl = tl, num = tr - tl + 1;
	}
	if (num == 0)
	{
    
    
		printf ("Nice work, Dima!");
		return 0;
	}
	printf ("%d\n", num);
	return 0;
}

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=324064555&siteId=291194637