zoukankan      html  css  js  c++  java
  • 洛谷P1396 营救

    P1396 营救

    题目描述

    “咚咚咚……”“查水表!”原来是查水表来了,现在哪里找这么热心上门的查表员啊!小明感动的热泪盈眶,开起了门……

    妈妈下班回家,街坊邻居说小明被一群陌生人强行押上了警车!妈妈丰富的经验告诉她小明被带到了t区,而自己在s区。

    该市有m条大道连接n个区,一条大道将两个区相连接,每个大道有一个拥挤度。小明的妈妈虽然很着急,但是不愿意拥挤的人潮冲乱了她优雅的步伐。所以请你帮她规划一条从s至t的路线,使得经过道路的拥挤度最大值最小。

    输入输出格式

    输入格式:

    第一行四个数字n,m,s,t。

    接下来m行,每行三个数字,分别表示两个区和拥挤度。

    (有可能两个区之间有多条大道相连。)

    输出格式:

    输出题目要求的拥挤度。

    输入输出样例

    输入样例#1:
    3 3 1 3							
    1 2 2
    2 3 1
    1 3 3
    
    输出样例#1:
    2
    

    说明

    数据范围

    30% n<=10

    60% n<=100

    100% n<=10000,m<=2n,拥挤度<=10000

    题目保证1<=s,t<=n且s<>t,保证可以从s区出发到t区。

    样例解释:

    小明的妈妈要从1号点去3号点,最优路线为1->2->3。

    两种做法:

    1.克鲁斯卡尔,生成树

    2.二分答案+spfa

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    using namespace std;
    int n,m,l=0x7fffffff,r=0,s,t,head[10010],num,ans=0x7fffffff;
    struct node{
        int to,pre,v;
    }e[40010];
    void Insert(int from,int to,int v){
        e[++num].to=to;
        e[num].v=v;
        e[num].pre=head[from];
        head[from]=num;
    }
    int q[10010],H,T;
    bool vis[10010];
    bool check(int limit){
        H=0;T=0;memset(vis,0,sizeof(vis));
        q[++T]=s;vis[s]=1;
        while(H!=T){
            int now=q[++H];
            if(now==t)return 1;
            for(int i=head[now];i;i=e[i].pre){
                int to=e[i].to;
                if(e[i].v>limit||vis[to])continue;
                vis[to]=1;
                if(to==t)return 1;
                else q[++T]=to;
            }
        }
        return 0;
    }
    int main(){
        scanf("%d%d%d%d",&n,&m,&s,&t);
        int x,y,z;
        for(int i=1;i<=m;i++){
            scanf("%d%d%d",&x,&y,&z);
            l=min(l,z);r=max(r,z);
            Insert(x,y,z);
            Insert(y,x,z);
        }
        while(l<=r){
            int mid=(l+r)>>1;
            if(check(mid))ans=mid,r=mid-1;
            else l=mid+1;
        }
        printf("%d
    ",ans);
        return 0;
    }
    二分答案+bfs
    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    #define maxn 10010
    struct node{
        int from,to,v;
    }e[maxn*4];
    int n,m,s,t,fa[maxn];
    int cmp(node x,node y){return x.v<y.v;}
    int find(int x){
        if(fa[x]==x)return fa[x];
        else return fa[x]=find(fa[x]);
    }
    int main(){
        scanf("%d%d%d%d",&n,&m,&s,&t);
        int x,y,z;
        for(int i=1;i<=m;i++){
            scanf("%d%d%d",&x,&y,&z);
            e[i].from=x;e[i].to=y;e[i].v=z;
        }
        sort(e+1,e+m+1,cmp);
        for(int i=1;i<=n;i++)fa[i]=i;
        for(int i=1;i<=m;i++){
            int f1=find(e[i].from),f2=find(e[i].to);
            int ans=0;
            if(f1!=f2){
                fa[f1]=f2;
                ans=e[i].v;
            }
            f1=find(s);f2=find(t);
            if(f1==f2){
                printf("%d",ans);
                return 0;
            }
        }
    }
    克鲁斯卡尔
    #include<iostream>
    #include<cstdio>
    #include<queue>
    #include<cstring>
    using namespace std;
    #define maxn 10010
    int n,m,s,t,num,head[maxn*2],ans,dis[maxn];
    struct node{
        int to,pre,v;
    }e[maxn*4];
    bool vis[maxn];
    void Insert(int from,int to,int v)
    {
        e[++num].to=to;
        e[num].v=v;
        e[num].pre=head[from];
        head[from]=num;
    }
    bool check(int x)
    {
        memset(vis,0,sizeof(vis));
        memset(dis,0x3f3f3f3f,sizeof(dis));
        queue<int>q;
        while(!q.empty())q.pop();
        q.push(s);
        dis[s]=0;vis[s]=1;
        while(!q.empty()){
            int cur=q.front();q.pop();vis[cur]=0;
            for(int i=head[cur];i;i=e[i].pre){
                int to=e[i].to;
                if(e[i].v<dis[to]){
                    dis[to]=e[i].v;
                    if(!vis[to]&&dis[to]<=x){
                        q.push(to);
                        vis[to]=1;
                    }
                }
            }
        }
        if(dis[t]>x)return 0;
        else return 1;
    }
    int main(){
        scanf("%d%d%d%d",&n,&m,&s,&t);
        int x,y,z;
        int l=0x7fffffff,r=0;
        for(int i=1;i<=m;i++){
            scanf("%d%d%d",&x,&y,&z);
            Insert(x,y,z);
            Insert(y,x,z);
            r=max(r,z);
            l=min(l,z);
        }
        while(l<=r){
            int mid=(l+r)>>1;
            if(check(mid))ans=mid,r=mid-1;
            else l=mid+1;
        }
        printf("%d",ans);
    }
    二分答案+spfa
  • 相关阅读:
    LeetCode 769. Max Chunks To Make Sorted
    LeetCode 845. Longest Mountain in Array
    LeetCode 1059. All Paths from Source Lead to Destination
    1129. Shortest Path with Alternating Colors
    LeetCode 785. Is Graph Bipartite?
    LeetCode 802. Find Eventual Safe States
    LeetCode 1043. Partition Array for Maximum Sum
    LeetCode 841. Keys and Rooms
    LeetCode 1061. Lexicographically Smallest Equivalent String
    LeetCode 1102. Path With Maximum Minimum Value
  • 原文地址:https://www.cnblogs.com/thmyl/p/7043735.html
Copyright © 2011-2022 走看看