• 洛谷 P1396 营救(二分答案)


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

    注意要用双向边!!

    1.二分+DFS:

    二分路径最大值,然后DFS,如果边权小于mid,那么可以走,否则不可以走。DFS只需要判断s->t是否连通:跑一边DFS,然后用vis看能否连通。

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cstring>
     4 using namespace std;
     5 const int N=20005;
     6 int n,m,s,t;
     7 int head[N],tot,dis[N],vis[N];
     8 struct node{
     9     int to,next,w;
    10 }edge[N<<1];
    11 void add(int u,int v,int w){
    12     edge[tot].to=v;
    13     edge[tot].next=head[u];
    14     edge[tot].w=w;
    15     head[u]=tot++;
    16 }
    17 void check(int u,int x){
    18     vis[u]=1;
    19     for(int i=head[u];i!=-1;i=edge[i].next){
    20         int v=edge[i].to;
    21         if(vis[v]) continue;
    22         if(edge[i].w<=x){
    23             check(v,x);    
    24         }
    25     }
    26 }
    27 int main(){
    28     memset(head,-1,sizeof(head));
    29     scanf("%d%d%d%d",&n,&m,&s,&t);
    30     for(int i=1;i<=m;i++){
    31         int u,v,w;
    32         scanf("%d%d%d",&u,&v,&w);
    33         add(u,v,w);add(v,u,w);
    34     }
    35     int l=0,r=10005;
    36     while(l<r){
    37         memset(vis,0,sizeof(vis));
    38         int mid=(l+r)>>1;
    39         check(s,mid);
    40         if(vis[t]) r=mid;
    41         else l=mid+1;
    42     }
    43     printf("%d",l);
    44     return 0;
    45 }
    DFS

    2.二分+BFS:

     与DFS思路相同。

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cstring>
     4 #include<queue>
     5 using namespace std;
     6 const int N=20005;
     7 int n,m,s,t;
     8 int head[N],tot,dis[N],vis[N];
     9 struct node{
    10     int to,next,w;
    11 }edge[N<<1];
    12 void add(int u,int v,int w){
    13     edge[tot].to=v;
    14     edge[tot].next=head[u];
    15     edge[tot].w=w;
    16     head[u]=tot++;
    17 }
    18 void check(int u,int x){
    19     queue<int> q;
    20     q.push(u); vis[u]=1;
    21     while(!q.empty()){
    22         int u=q.front(); q.pop();
    23         for(int i=head[u];i!=-1;i=edge[i].next){
    24             int v=edge[i].to;
    25             if(edge[i].w>x) continue; 
    26             if(vis[v]) continue;
    27             vis[v]=1;
    28             q.push(v);
    29         }
    30     }
    31 }
    32 int main(){
    33     memset(head,-1,sizeof(head));
    34     scanf("%d%d%d%d",&n,&m,&s,&t);
    35     for(int i=1;i<=m;i++){
    36         int u,v,w;
    37         scanf("%d%d%d",&u,&v,&w);
    38         add(u,v,w);add(v,u,w);
    39     }
    40     int l=0,r=10005;
    41     while(l<r){
    42         memset(vis,0,sizeof(vis));
    43         int mid=(l+r)>>1;
    44         check(s,mid);
    45         if(vis[t]) r=mid;
    46         else l=mid+1;
    47     }
    48     printf("%d",l);
    49     return 0;
    50 }
    BFS

    3.二分+并查集:

    用并查集维护s,t是否连通。如果边权小于等于mid,那么就将两个点合并。最后看看find(s),find(t)是否相同。

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cstring>
     4 #include<queue>
     5 using namespace std;
     6 const int N=20005;
     7 int n,m,s,t;
     8 int head[N],tot,dis[N],vis[N],f[N];
     9 struct node{
    10     int to,next,w;
    11 }edge[N<<1];
    12 struct Node{
    13     int u,v,w;
    14 }q[N];
    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 int find(int x){
    22     if(f[x]!=x) f[x]=find(f[x]);
    23     return f[x];
    24 }
    25 void unionn(int u,int v){
    26     int r1=find(u),r2=find(v);
    27     if(r1!=r2) f[r1]=r2;    
    28 }
    29 bool check(int x){
    30     for(int i=1;i<=n;i++) f[i]=i;
    31     for(int i=1;i<=m;i++){
    32         if(q[i].w<=x){
    33             unionn(q[i].u,q[i].v);
    34         }
    35     }
    36     if(find(s)==find(t)) return 1;
    37     return 0;
    38 }
    39 int main(){
    40     memset(head,-1,sizeof(head));
    41     scanf("%d%d%d%d",&n,&m,&s,&t);
    42     for(int i=1;i<=m;i++){
    43         int u,v,w;
    44         scanf("%d%d%d",&u,&v,&w);
    45         q[i].u=u; q[i].v=v; q[i].w=w;
    46     }
    47     int l=0,r=10005;
    48     while(l<r){
    49         memset(vis,0,sizeof(vis));
    50         int mid=(l+r)>>1;
    51         if (check(mid)) r=mid;
    52         else l=mid+1;
    53     }
    54     printf("%d",l);
    55     return 0;
    56 }
    并查集
  • 相关阅读:
    MySQL优化—工欲善其事,必先利其器(2)
    MySQL优化—工欲善其事,必先利其器之EXPLAIN
    Linux工具安装和常用配置
    .Net Core配置文件介绍
    Centos7上开发.Net Core项目
    VMWare的host-only/bridged/NAT连接图文介绍
    Quartz.net 3.x使用总结(二)——Db持久化和集群
    Vuex实现状态管理
    Quartz.net 3.x使用总结(一)——简单使用
    C#获取根目录的方法总结
  • 原文地址:https://www.cnblogs.com/New-ljx/p/13875319.html
Copyright © 2020-2023  润新知