• 340. 通信线路


    一眼二分。。。然后就没思路了。。。

    • 二分当前路径上第\(k+1\)大的边权,要求最小化第\(k+1\)大的边权,故考虑二分。
    • 二分的判定条件是当前路径上边权比\(mid\)大的边数应不超过\(k\)

    于是现在核心问题是如何当前二分的值为\(mid\)的情况下,是否存在一条从\(1\)\(n\)的路径,边权大于\(mid\)的边数不超过\(k\)

    问题转化如下:

    • 将大于\(mid\)的边权赋为\(1\),小于等于\(mid\)的边权赋为\(0\)
    • 根据贪心思想,我们在新图上求一遍最短路,若\(dist[n] <= k\),说明存在一条从\(1\)\(n\)的路径,边权大于\(mid\)的边数不超过\(k\),反之不存在

    而最短路的求法可采用\(0-1 BFS\)

    注意:二分有边界向右多取一个,据此判断无解情况

    const int N=1010;
    vector<PII> g[N];
    int dist[N];
    bool vis[N];
    int n,m,k;
    
    int check(int mid)
    {
        memset(dist,0x3f,sizeof dist);
        memset(vis,0,sizeof vis);
        deque<int> q;
        dist[1]=0;
        q.push_back(1);
    
        while(q.size())
        {
            int t=q.front();
            q.pop_front();
        
            if(t == n) return dist[t];
            
            if(vis[t]) continue;
            vis[t]=true;
    
            for(int i=0;i<g[t].size();i++)
            {
                int j=g[t][i].fi,w=(g[t][i].se>mid);
                if(dist[j] > dist[t] + w)
                {
                    dist[j]=dist[t]+w;
                    if(!w) q.push_front(j);
                    else q.push_back(j);
                }
            }
        }
        return INF;//1到n不连通
    }
    
    int main()
    {
        cin>>n>>m>>k;
    
        int l=0,r=0;
        while(m--)
        {
            int a,b,c;
            cin>>a>>b>>c;
            g[a].pb({b,c});
            g[b].pb({a,c});
            r=max(r,c);
        }
        int tr=r;
        r++;
    
        while(l<r)
        {
            int mid=l+r>>1;
            if(check(mid)<=k) r=mid;
            else l=mid+1;
        }
    
        if(r == tr+1) puts("-1");
        else cout<<l<<endl;
        //system("pause");
    }
    

    分层图解法

    • 最大边尽量小
    const int N=1010;
    struct Node
    {
        int dis,u,cnt;
        bool operator>(const Node &W) const
        {
            return dis>W.dis;
        }
    };
    vector<PII> g[N];
    int dist[N][N];
    bool vis[N][N];
    int n,m,k;
    
    void dijkstra()
    {
        memset(dist,0x3f,sizeof dist);
        priority_queue<Node,vector<Node>,greater<Node> > heap;
        dist[1][0]=0;
        heap.push({0,1,0});
    
        while(heap.size())
        {
            int t=heap.top().u,c=heap.top().cnt;
            heap.pop();
    
            if(vis[t][c]) continue;
            vis[t][c]=true;
    
            for(int i=0;i<g[t].size();i++)
            {
                int j=g[t][i].fi,w=g[t][i].se;
                if(c+1<=k && dist[j][c+1]>dist[t][c])
                {
                    dist[j][c+1]=dist[t][c];
                    heap.push({dist[j][c+1],j,c+1});
                }
                if(dist[j][c]>max(dist[t][c],w))
                {
                    dist[j][c]=max(dist[t][c],w);
                    heap.push({dist[j][c],j,c});
                }
            }
        }
    
    }
    
    int main()
    {
        cin>>n>>m>>k;
    
        while(m--)
        {
            int a,b,c;
            cin>>a>>b>>c;
            g[a].pb({b,c});
            g[b].pb({a,c});
        }
    
        dijkstra();
        
        int res=INF;
        for(int i=0;i<=k;i++) res=min(res,dist[n][i]);
        if(res == INF) puts("-1");
        else cout<<res<<endl;
        //system("pause");
    }
    
  • 相关阅读:
    CMS4.0——后知后觉
    《Mysql 入门很简单》(读后感②)
    《Mysql 入门很简单》(读后感①)
    Mysql 入门
    jQuery ajax中serialize()方法增加其他参数
    简单语法
    音频——H5 audio
    js 中的break continue return
    vue再次入手(数据传递②)
    vue再次入手(数据传递①)
  • 原文地址:https://www.cnblogs.com/fxh0707/p/13740208.html
Copyright © 2020-2023  润新知