codeforces 366D 并查集

//给你一个无向图,图的每条边有一个范围,所选数x要在这个范围能过这条边

//求x最大范围

//枚举所有的边的右边,对于所选右边找左边最小值,用并查集判断是否可行

#include<cstdio>

#include<cstring>

#include<algorithm>

#include<iostream>

using namespace std ;

const int maxn = 1010;

int F[maxn] ;

int find(int x)

{

if(x == F[x])return x ;

else return F[x] = find(F[x]) ;

}

int join(int x,int y)

{

int fx = find(x) ;

int fy = find(y) ;

if(fx  != fy)

F[fx] = fy ;

}

struct node

{

int x , y ,l ,r;

}a[maxn*3] ;

bool cmp(struct node a ,struct node b)

{

return a.l < b.l ;

}

int  main()

{

int n , m ;

while(~scanf("%d%d" ,&n , &m))

{

int x , y , l ,r ;

for(int i = 1;i <= m;i++)

scanf("%d%d%d%d" ,&a[i].x , &a[i].y  ,&a[i].l ,&a[i].r) ;

sort(a+1 ,a+1+m,cmp) ;

int ans = 0 ;

for(int i = 1;i <= m;i++)

{

for(int j = 1;j <= n;j++)

F[j] = j ;

for(int j = 1;j <= m;j++)

{

if(a[j].l > a[i].r)break;

if(a[j].r < a[i].r)continue ;

join(a[j].x ,a[j].y);

if(find(1) == find(n))

{

ans = max(ans , a[i].r - a[j].l + 1) ;

break ;

}

}

}

if(ans)printf("%d\n",ans) ;

else puts("Nice work, Dima!");

}

return 0;

}

时间: 2024-10-13 11:56:06

codeforces 366D 并查集的相关文章

0-1-Tree CodeForces - 1156D (并查集)

大意: 给定树, 边权为黑或白, 求所有有向路径条数, 满足每走过一条黑边后不会走白边. 这题比赛的时候想了个假算法, 还没发现..... 显然所求的路径要么全黑, 要么全白, 要么先全白后全黑, 所以可以用并查集将相邻同色边合并即可. #include <iostream> #include <random> #include <algorithm> #include <cstdio> #include <math.h> #include &l

Codeforces 722C(并查集 + 思维)

题目链接:http://codeforces.com/problemset/problem/722/C 思路: 题目给的操作数从第 1 个到第 N 个数是删除原数组中的一个数, 那么反过来从后往前就是增加原数组中的一个数, 每增加一个值, 那么就有四种情况: 第一种和前后都不连续, 即自成一个集合; 第二种:和前面的数连续, 即和前一个数在一个集合; 第三种和之后一个数连续, 即和之后的一个数在一个集合; 第四种既和前面一个数连续也和后面一个数连续,那么说明前后两个集合被这个数合并成一个集合.

CodeForces 566D 并查集集合合并

1 #include <stdio.h> 2 #include <algorithm> 3 #define MAX 100000 4 #define LL long long 5 #define unsigned U 6 //using namespace std; 7 int cas=1,T; 8 int fa[MAX*2+10],next[MAX*2+10],n,q; 9 void init(int n) 10 { 11 for(int i=1;i<=n;i++) { f

codeforces 455C 并查集

传送门 给n个点, 初始有m条边, q个操作. 每个操作有两种, 1是询问点x所在的连通块内的最长路径, 就是树的直径. 2是将x, y所在的两个连通块连接起来,并且要合并之后的树的直径最小,如果属于同一个连通块就忽视这个操作. 先dfs出每个连通块的初始直径, 然后合并的话就是len[x] = max( (len[x]+1)/2+(len[y]+1)/2+1, max(len[x], len[y]));  然后搞一搞就好了. 一开始写bfs写挫了一直超时,  只好改成dfs...... 1 #

Codeforces Round #396 (Div. 2) D题Mahmoud and a Dictionary(并查集)解题报告

Mahmoud wants to write a new dictionary that contains n words and relations between them. There are two types of relations: synonymy (i. e. the two words mean the same) and antonymy (i. e. the two words mean the opposite). From time to time he discov

Codeforces 755C:PolandBall and Forest(并查集)

http://codeforces.com/problemset/problem/755/C 题意:该图是类似于树,给出n个点,接下来p[i]表示在树上离 i 距离最远的 id 是p[i],如果距离相等则p[i]是 id 较小的点. 思路:一开始没什么想法,画几分钟图发现不到什么东西,后来想着 i 和 p[i] 有关系,那么就代表 i 和 p[i] 是属于同一棵树,那么不就是并查集了嘛.抱着试一试的心态搞了一下居然过了. 1 #include <cstdio> 2 #include <c

Educational Codeforces Round 14 D. Swaps in Permutation (并查集orDFS)

题目链接:http://codeforces.com/problemset/problem/691/D 给你n个数,各不相同,范围是1到n.然后是m行数a和b,表示下标为a的数和下标为b的数可以交换无数次.问你最后字典序最大的数列是什么. 将下面的a和b用并查集联系起来存到祖节点对应的数组中,然后从大到小排序数组,最后依次按照父节点的数组中的顺序输出. 也可以用dfs的方法解(略麻烦),形成一个环路的就在一个数组中... 1 //并查集 2 #include <bits/stdc++.h> 3

CodeForces 510B 无向图找环的两种方法(搜索与并查集)

题目连接:http://codeforces.com/problemset/problem/510/B 解法: dfs 每次把父节点的值记录并传递下去,判断一下新达到节点: (1)没有走过 → 继续搜索: (2)走过&&不是父节点(对于本题步数也要>=4) → 找到环: 并查集 每个节点映射成 i*m+j从起点开始分别把它下面与于右面的节点加进来,如果发现有节点已经在集合中,那么环已经找到了. DFS: #include<cstdio> #include<cstdl

Codeforces Round #254 (Div. 2) B. DZY Loves Chemistry (并查集)

题目链接 昨天晚上没有做出来,刚看题目的时候还把题意理解错了,当时想着以什么样的顺序倒,想着就饶进去了, 也被题目下面的示例分析给误导了. 题意: 有1-n种化学药剂  总共有m对试剂能反应,按不同的次序将1-n种试剂滴入试管,如果正在滴入的试剂能与已经滴入 的试剂反应,那么危险数*2,否则维持不变.问最后最大的危险系数是多少. 分析:其实这个题根本不用考虑倒入的顺序,只是分块就行,结果就是每个子集里元素的个数-1 和  的2的幂. 1 #include <iostream> 2 #inclu