P5122 Fine Dining G 题解
题目分析
分层图最短路。我们可以借助题中所给边建两层一模一样的图,对于有干草垛的节点,在两层图中的相应节点间连一条边权为干草垛美味程度相反数的边,再以 \(n\) 为起点跑一遍SPFA。比较两层图上对应节点的最短路长度,如果 \(dis_{i} > dis_{n+i}\) 说明可以找到合法的干草垛,输出 \(0\),否则输出 \(1\)。
坑点
- 由于有负权边,不能使用dijkstra求最短路。
- 点数要开到 \(10^{5}\) 而不是题目中的 \(10^{4}\)。
- 对于有多个干草垛的牧场,只考虑美味程度最大的。
代码实现
#include<bits/stdc++.h>
using namespace std;
struct node{
int v,dis;
};
vector<node> p[100005];
queue<int>q;
int de[100005],dis[100005];
signed main(){
int n,m,k;
scanf("%d%d%d",&n,&m,&k);
for(int i=1;i<=m;i++){
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
p[u].push_back((node){v,w});
p[v].push_back((node){u,w});
p[u+n].push_back((node){v+n,w});//建分层图
p[v+n].push_back((node){u+n,w});
}
for(int i=1;i<=k;i++){
int num,w;
scanf("%d%d",&num,&w);
de[num]=max(de[num],w);
}
for(int i=1;i<=n;i++){
if(de[i])p[i].push_back((node){i+n,-de[i]});//相应节点建负权边
dis[i]=dis[i+n]=0x3f3f3f3f;
}
dis[n]=0;
q.push(n);
while(!q.empty()){
int u=q.front();
q.pop();
for(int i=0;i<p[u].size();i++){
int v=p[u][i].v;
if(dis[v]>dis[u]+p[u][i].dis){
dis[v]=dis[u]+p[u][i].dis;
q.push(v);
}
}
}
for(int i=1;i<n;i++){
if(dis[i]<dis[i+n])printf("%d\n",0);
else printf("%d\n",1);
}
}
注:由于铸币洛谷管理员,本题解未在洛谷发布。

浙公网安备 33010602011771号