题解: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
*/

浙公网安备 33010602011771号