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");
}
posted @ 2020-09-27 16:18  Dazzling!  阅读(113)  评论(0编辑  收藏  举报