其他分享
首页 > 其他分享> > [Acwing] 通信线路 二分|DP + 最短路

[Acwing] 通信线路 二分|DP + 最短路

作者:互联网

前言

简直不是一般的难!!!
传送门 :

题目分析

路径代价
每一条路径上 最大的边是 这条路的代价

对于k
可以让路径免费,只不过是多加了一条 为0 的重边

最后题目转换为 :

我们可以设置 k k k条边权为 0 0 0的边,让我们求从 1 1 1到 n n n的最小花费


令 f [ x , p ] f[x,p] f[x,p] 表示从 1号节点 到x号节点,途中经过 p 条权值为0的边

因此

因此对于答案 我们只需要枚举所有的 k即可

CODE

///d[x,p] 表示从 1号节点 到 x 号节点 途径 p条权值0的边


#include <bits/stdc++.h>
using namespace std;
const int N = 4e3+10,M =4e4+10;
int h[N],e[M],ne[M],w[M],idx;
int n,m,k;
int f[N][N];
int st[N];

void add(int a,int b,int c)
{
    e[idx] = b,ne[idx] = h[a],w[idx] = c,h[a] = idx++;
}

void spfa(int s )
{
    memset(f,0x3f,sizeof f);
    f[s][0] = 0;
    ///从1 到 s 号节点 途0条边权为0的边
    st[s] = 1;
    queue<int> q;
    q.push(s);

    while(!q.empty())
    {
        int t = q.front();
        q.pop();
        st[t] = 0 ;
        for(int i= h[t];~i;i=ne[i])
        {
            int j = e[i];
            int z = w[i];
            int w = max(f[t][0],z);

            if(f[j][0] >w)
            {
                f[j][0] = w;
                if(!st[j])
                {
                    q.push(j),st[j] = 1;
                }
            }

            for(int p=1;p<=k;p++)
            {
                int w = min(f[t][p-1],max(f[t][p],z));

                if(f[j][p]>w)
                {
                    f[j][p] = w;
                    if(!st[j])
                    {
                        q.push(j);
                        st[j] = 1;

                    }
                }
            }


        }
    }
}
void solve()
{
    cin>>n>>m>>k;
    memset(h,-1,sizeof h);

    for(int i=1; i<=m; i++)
    {
        int a,b,c;
        cin>>a>>b>>c;
        add(a,b,c),add(b,a,c);
    }

    spfa(1);
    int ans = 1e9;
    for(int i=0;i<=k;i++)
    ans = min(ans,f[n][i]);

    if(ans == 1e9)
    cout<<-1<<endl;
    else
    cout<<ans<<endl;


}
int main()
{
    ios::sync_with_stdio(false);
    solve();
    return 0;
}

标签:idx,int,max,ne,st,节点,通信线路,DP,Acwing
来源: https://blog.csdn.net/qq_34364611/article/details/120990931