题解:AT_joi2015ho_c JOI 公園 (JOI Park)

模拟赛签到题。

题目大意

给定 \(n\) 个节点 \(m\) 条边的无向图和一个值 \(V\),可以选取一个值 \(c\),代价是将所有 \(1\) 为起点的单源最短路小于 \(c\) 的点之间的边除外,所有边的权值和加上 \(c\times V\),求最小代价。

分析

先 dijkstra 跑一遍最短路,然后直接模拟。

先枚举 \(c\),不难发现不需要连续地枚举 \(c\),只需要离散地枚举所有 \(dis_i\) 即可,因为卡在中间只会有多余的贡献,下调 \(c\) 值一定更优,故枚举复杂度是 \(\Theta(n)\) 的。

接下来考虑如何计算每个 \(c\) 值下的 \(\sum w\),使用二元组记录所有 \((dis_v,v)\) 然后排序,然后按照顺序依次开放节点并枚举这个点能到的边,要是能到就移除该边的贡献,最后动态更新答案即可。

Code

#include <bits/stdc++.h>
#define int long long
#define umap unordered_map
#define vint vector<int>
#define ll long long
#define pii pair<int,int>
#define all(x) x.begin(),x.end()
#define ull unsigned long long
#define uint unsigned int
#define rg register
#define il inline
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define sqr(x) ((x)*(x))
using namespace std;
const int INF=0x3f3f3f3f3f3f3f3f;
inline int read()
{
    int w=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9')
    {
        if(ch=='-') f=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9')
    {
        w=(w<<1)+(w<<3)+(ch^48);
        ch=getchar();
    }
    return w*f;
}
inline void write(int x)
{
    if(x<0)
    {
        putchar('-');
        x=-x;
    }
    if(x>9) write(x/10);
    putchar(x%10+'0');
}

const int N=3e5+10,M=2e5+10;
int n,m,V;
struct node
{
    int v,w;
    node(int v=0,int w=0):v(v),w(w){}
    bool operator <(const node &b)const
    {
        return w>b.w;
    }
};
vector<node> G[N];
int dis[N],vis[N];
node pre[N];
int all_cost;
vint dist;
void dijkstra()
{
    priority_queue<node> Q;
    fill(dis,dis+n+1,INF);
    memset(dis,0x3f,sizeof dis);
    Q.push({1,0}),dis[1]=0;
    while(!Q.empty())
    {
        int u=Q.top().v;
        Q.pop();
        if(vis[u]) continue;
        vis[u]=1;
        for(node &k:G[u])
        {
            int v=k.v,w=k.w;
            if(dis[v]>dis[u]+w)
            {
                dis[v]=dis[u]+w;
                pre[v]={u,w};
                Q.push({v,dis[v]});
            }
        }
    }
}
struct state
{
    int u,dis;
    bool operator <(const state &b)const
    {
        return dis<b.dis;
    }
};
int ans=INF;
vector<state> res;
map<pii,int> book;
unordered_map<int,int> tag,reach;
pii my_mp(int u,int v)
{
    return make_pair(min(u,v),max(u,v));
}
signed main()
{
    // freopen("in.txt","r",stdin);
    cin>>n>>m>>V;
    for(int i=1,u,v,w;i<=m;++i)
    {
        u=read(),v=read(),w=read();
        G[u].push_back({v,w});
        G[v].push_back({u,w});
        all_cost+=w;
    }
    dijkstra();
    for(int u=1;u<=n;++u)
    {
        res.push_back({u,dis[u]});
    }
    sort(all(res));
    ans=all_cost;
    for(auto i:res)
    {
        auto [u,dis]=i;
        reach[u]=1;
        for(auto k:G[u])
        {
            if(reach[k.v])
            {
                all_cost-=k.w;
            }
        }
        ans=min(ans,all_cost+dis*V);
    }
    cout<<ans<<endl;
    return 0;
}
/*
5 5 2
2 3 1
3 1 2
2 4 3
1 2 4
2 5 5
*/
/*
2 1 66
2 1 7

5 4 10
1 2 3
2 3 4
3 4 3
4 5 5

6 5 2
1 2 2
1 3 4
1 4 3
1 5 1
1 6 5
*/

posted @ 2025-05-01 14:29  vanueber  阅读(18)  评论(0)    收藏  举报