洛谷 P1525 关押罪犯(并查集|二分图判定&二分答案)

题目链接:https://www.luogu.com.cn/problem/P1525

 

解法一:并查集

按照w排序,看每一对u、v,如果两个在同一个并查集中,那么输出w,即为最大。

如果不在:当u还没有敌人时,则敌人为v;如果有敌人,那么u原来的敌人e[u]和现在敌人v为一个并查集。同理。

AC代码:

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 const int N=100005;
 7 int n,m;
 8 int f[N],e[N];
 9 struct node{
10     int u,v,w;
11 }q[N];
12 bool cmp(node a,node b){
13     return a.w>b.w;
14 }
15 int find(int x){
16     if(f[x]!=x) f[x]=find(f[x]);
17     return f[x];
18 }
19 int main(){
20     scanf("%d%d",&n,&m);
21     for(int i=1;i<=m;i++)
22         scanf("%d%d%d",&q[i].u,&q[i].v,&q[i].w);
23     sort(q+1,q+m+1,cmp);
24     for(int i=1;i<=n;i++) f[i]=i;
25     for(int i=1;i<=m;i++){
26         int u=q[i].u,v=q[i].v;
27         int r1=find(u),r2=find(v);
28         if(r1==r2) {printf("%d",q[i].w); return 0;}
29         if(!e[u]) e[u]=v;
30         else f[find(e[u])]=find(v);
31         if(!e[v]) e[v]=u;
32         else f[find(e[v])]=find(u);
33     }
34     printf("0");
35     return 0;
36 }
AC代码

 

解法二:二分图判定+二分答案

因为题目求的是最大值最小,所以可以用二分答案。二分这个答案,然后将大于等于这个二分的答案的边的两边的点进行染色,看是否是二分图。(自己的二分答案写的好奇葩

AC代码:

 1 #include<cstdio>
 2 #include<queue>
 3 #include<cstring>
 4 #include<iostream>
 5 using namespace std;
 6 const int N=100005;
 7 int n,m,tot;
 8 int head[N],color[N];
 9 struct node{
10     int to,next,w;
11 }edge[N<<1];
12 void init(){
13     memset(head,-1,sizeof(head));
14 }
15 void add(int u,int v,int w){
16     edge[tot].to=v;
17     edge[tot].next=head[u];
18     edge[tot].w=w;
19     head[u]=tot++;
20 }
21 bool work(int x){
22     queue<int> q;
23     memset(color,0,sizeof(color));
24     for(int i=1;i<=n;i++){
25         if(!color[i]){
26             q.push(i);
27             color[i]=1;
28             while(!q.empty()){
29                 int u=q.front(); q.pop();
30                 for(int i=head[u];i!=-1;i=edge[i].next){
31                     int v=edge[i].to;
32                     if(edge[i].w>=x){
33                         if(!color[v]){
34                             q.push(v);
35                             if(color[u]==1) color[v]=2;
36                             else color[v]=1;
37                         }
38                         else if(color[v]==color[u]) return 0;
39                     }
40                 }
41             }
42         }
43     }
44     return 1;
45 }
46 int main(){
47     init();
48     int l=0,r=0,ans=0;
49     scanf("%d%d",&n,&m);
50     for(int i=1;i<=m;i++){
51         int u,v,w;
52         scanf("%d%d%d",&u,&v,&w);
53         r=max(r,w);
54         add(u,v,w); add(v,u,w);
55     }
56     r++;
57     while(l<=r){
58         int m=(l+r)>>1;
59         if(work(m)) {ans=m; r=m-1;}
60         else l=m+1;
61     }
62     if(ans==0) {printf("0"); return 0;}
63     else printf("%d",ans-1);
64     return 0;
65 }
AC代码

 

posted @ 2020-08-09 16:49  dfydn  阅读(103)  评论(0编辑  收藏  举报