专栏文章
霉利的题解(2)
P1342题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @miqmqagv
- 此快照首次捕获于
- 2025/12/04 07:19 3 个月前
- 此快照最后确认于
- 2025/12/04 07:19 3 个月前
这道题我们可以发现可以分为两个部分。
- 第一是学生去车站的部分。(一点到多点,dij或spfa)
- 第二是学生从车站回来。(多点到一点)
我们如果可以将图反着存,那么就可以将多点到一点变成一点到多点。
代码如下
CPP#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N=1e6+10;
ll n,m,x,y,l,dis[N],dis1[N],f[N],f1[N],pre[N],pre1[N],cnt,cnt1,q[5*N],q1[5*N],sum=0;//因为要有正反两图,所以我们要定义双份;
struct edge{
ll f,t,l,n;
}a[5*N],b[5*N];
void add(ll x,ll y,ll l){
a[++cnt].f=x;
a[cnt].t=y;
a[cnt].l=l;
a[cnt].n=pre[x];
pre[x]=cnt;
}//链式前向星(正图)
void add1(ll y,ll x,ll l){
b[++cnt1].f=y;
b[cnt1].t=x;
b[cnt1].l=l;
b[cnt1].n=pre1[y];
pre1[y]=cnt1;
}//链式前向星(反图)
//正图spfa模版
void spfa(){
ll head=1,tail=1;
q[1]=1;
f[1]=1;
dis[1]=0;
while(head<=tail){
ll from=q[head];
for(int i=pre[from];i;i=a[i].n){
ll to=a[i].t;
ll len=a[i].l;
if(dis[from]+len<dis[to]){
dis[to]=dis[from]+len;
if(f[to]==0){
f[to]=1;
q[++tail]=to;
}
}
}
f[from]=0;
head++;
}
}
//反图spfa
void spfa1(){
ll head=1,tail=1;
q1[1]=1;
f1[1]=1;
dis1[1]=0;
while(head<=tail){
ll from=q1[head];
for(int i=pre1[from];i;i=b[i].n){
ll to=b[i].t;
ll len=b[i].l;
if(dis1[from]+len<dis1[to]){
dis1[to]=dis1[from]+len;
if(f1[to]==0){
f1[to]=1;
q1[++tail]=to;
}
}
}
f1[from]=0;
head++;
}
}
int main(){
scanf("%lld%lld",&n,&m);
for(int i=1;i<=m;i++){
scanf("%lld%lld%lld",&x,&y,&l);
add(x,y,l);//正着存入
add1(y,x,l);//反着存入
}
for(int i=1;i<=n;i++){
dis[i]=2e9+10;
dis1[i]=2e9+10;
}//初始化
spfa();
spfa1();
for(int i=2;i<=n;i++){
sum+=dis[i]+dis1[i];//将所有的点费用加起来
}
printf("%lld",sum);
}
注意要用快读或者c的输入输出,不然只有小概率得满分(为了保险起见最好加上)
作者亲自实践:(
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...