洛谷1525并查集+分集合

题目链接:https://www.luogu.com.cn/problem/list?keyword=1525&page=1

题目给出一些点对之间的权值,要求把点对分到两个集合之中,使得两个集合中的最大边的值最小。我们考虑到将点对分成两个集合可以用并查集的分集合方法得到,1-n表示的是一个集合,n+1-2*n表示的是另一个集合,因为我们不会人为的将x和x+n合并,所以x+n所在集合与x所在的集合一定是相互排斥的,也就是说x+n集合是所有不和x一个集合的结点构成的集合。本题只要贪心地扫一遍最大边就可以。将边排序之后我们逐个选择最大边,分为两种情况。

1、如果最大边的两个结点不在同一个集合中,我们就把他分到两个集合中,因为如果合并到一个集合之中就已经结束了,但是接下来可能会有更小的边满足条件,所以分在两个集合之中。

2、如果最大边的两个结点已经在同一个集合中,这条边就是答案,因为他们已经是某个集合中的最大边,而且两个集合中已经没有任何一条边比它大。此时就实现了最大边的最小化。

代码如下:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef unsigned int ui;
 4 typedef long long ll;
 5 typedef unsigned long long ull;
 6 #define pf printf
 7 #define mem(a,b) memset(a,b,sizeof(a))
 8 #define prime1 1e9+7
 9 #define prime2 1e9+9
10 #define pi 3.14159265
11 #define lson l,mid,rt<<1
12 #define rson mid+1,r,rt<<1|1
13 #define scand(x) scanf("%llf",&x) 
14 #define f(i,a,b) for(int i=a;i<=b;i++)
15 #define scan(a) scanf("%d",&a)
16 #define mp(a,b) make_pair((a),(b))
17 #define P pair<int,int>
18 #define dbg(args) cout<<#args<<":"<<args<<endl;
19 #define inf 0x3f3f3f3f
20 const int maxn=1e6+10;
21 int n,m,t;
22 inline int read(){
23     int ans=0,w=1;
24     char ch=getchar();
25     while(!isdigit(ch)){if(ch=='-')w=-1;ch=getchar();}
26     while(isdigit(ch))ans=(ans<<3)+(ans<<1)+ch-'0',ch=getchar();
27     return ans*w;
28 }
29 struct node{
30     int u,v,w;
31 }p[maxn];
32 int f[maxn];
33 void init()
34 {
35     f(i,1,2*n)f[i]=i;
36 }
37 int find(int x )
38 {
39     return x==f[x]?x:f[x]=find(f[x]);
40 }
41 bool cmp(node& a,node& b)
42 {
43     return a.w>b.w;
44 }
45 int main()
46 {
47     //freopen("input.txt","r",stdin);
48     //freopen("output.txt","w",stdout);
49     std::ios::sync_with_stdio(false);
50     n=read(),m=read();
51     init();
52     f(i,1,m)
53     {
54         p[i].u=read(),p[i].v=read(),p[i].w=read();
55     }
56     sort(p+1,p+m+1,cmp);
57     f(i,1,m)
58     {
59         int x=find(p[i].u);
60         int y=find(p[i].v);
61         if(x==y)
62         {
63             pf("%d",p[i].w);
64             return 0;
65         }
66         else
67         {
68             f[x]=find(n+p[i].v);//注意传的是结点 
69             f[y]=find(n+p[i].u);
70         }
71     }
72     pf("0");
73     return 0;
74  } 
原文地址:https://www.cnblogs.com/randy-lo/p/12566947.html