最小最大边-地铁修建

题目大意:

  A市有n个交通枢纽,其中1号和n号非常重要,为了加强运输能力,A市决定在1号到n号枢纽间修建一条地铁。
  地铁由很多段隧道组成,每段隧道连接两个交通枢纽。经过勘探,有m段隧道作为候选,两个交通枢纽之间最多只有一条候选的隧道,没有隧道两端连接着同一个交通枢纽。
  现在有n家隧道施工的公司,每段候选的隧道只能由一个公司施工,每家公司施工需要的天数一致。而每家公司最多只能修建一条候选隧道。所有公司同时开始施工。
  作为项目负责人,你获得了候选隧道的信息,现在你可以按自己的想法选择一部分隧道进行施工,请问修建整条地铁最少需要多少天。

思路:

  题目第一眼看过去以为是最小生成树,其实应该是和A*类似,具体正确性,我也没有做具体的深入思考,大概应该是每次搜到一个点的时候它的mincost应该是前驱结点的mincost和当前的边权取一个较大的值,但是要保证这个最大值最小,所以第一次访问到该点的时候就肯定是最小最大边

代码:

#include <iostream>
#include <algorithm>
#include <queue>
#include <map>
#include <cstring>
using namespace std;
const int N = 1e5+10;
const int M = 4e5+10;

struct edg{
    int a,b,c;
    edg(){}
    edg(int a,int b,int c){
        this->a=a;
        this->b=b;
        this->c=c;
    }
    bool operator < (const edg& x)const{
        return this->c>x.c;
    }
};
vector<edg> edgs[N];
priority_queue<edg> q;
int vi[N];
int minc[M];

int main(){
    int n,m;
    cin>>n>>m;
    for(int i=0;i<m;i++){
        int a,b,c;
        cin>>a>>b>>c;
        edgs[a].push_back(edg(a,b,c));
        edgs[b].push_back(edg(b,a,c));
    }
    memset(minc,0x3f,sizeof minc);
    minc[1]=0;
    vi[1]=1;
    for(int i=0;i<edgs[1].size();i++){
        q.push(edgs[1][i]);
    }
    
    while(q.size()){
        edg t=q.top();
        q.pop();
        int a=t.a;
        int b=t.b;
        vi[b]=1;
        int c=t.c;
        minc[b]=min(minc[b],max(minc[a],c));
        if(b==n)break;
        for(int i=0;i<edgs[b].size();i++){
            if(!vi[edgs[b][i].b]){
                q.push(edgs[b][i]);
            }
        }
    }
    cout<<minc[n]<<endl;
}

 

posted @ 2020-08-24 17:04  kstranger  阅读(169)  评论(0)    收藏  举报