请 柬 请柬 请柬
L u o g u P 1342 Luogu P1342 LuoguP1342
题目背景
在电视时代,没有多少人观看戏剧表演。 Malidinesia 古董喜剧演员意识到这一事实,他们想宣传剧院,尤其是古色古香的喜剧片。
题目描述
他们已经打印了请帖和所有必要的信息和计划。许多学生被雇来分发这些请柬。每个学生志愿者被指定一个确切的公共汽车站,他或她将留在那里一整天,邀请人们参与。
这里的公交系统是非常特殊的:共有 n 个站点和 m 个线路,所有的线路都是单向的,连接两个站点。公共汽车离开起始点,到达目的地之后又空车返回起始点。
学生每天早上从总部所在的 1 号站点出发,乘公交车到一个预定的站点邀请乘客。每个站点都被安排了一名学生。在一天结束的时候,所有的学生都回到总部。现在需要知道的是,学生所需的公交费用的总和最小是多少。
输入格式
输入的第一行是两个整数,代表站点个数 n 和线路条数 m。
第 2 到第 (m + 1) 行,每行三个整数 u, v, w代表存在一条从 u 出发到达 v 的线路,费用为 w。
输出格式
输出一行一个整数,表示最小费用。
输入输出样例
输入样例
4 6
1 2 10
2 1 60
1 3 20
3 4 10
2 4 5
4 1 50
输出样例
210
说明/提示
数据规模与约定
对于 100% 的数据,保证:
1≤n,m≤10^6
1≤u,v≤n
1≤w≤10^9
从 1 出发可以到达所有的站点
解题思路
- 这道题和另一道题基本一致,只是数据范围变大了,要使用 longlong 即可
- 详情思路在 【LuoguP1629】邮递员送信
代码如下
#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#include<algorithm>
using namespace std;
long long n,m,p,u,v,w,ans,t[1000001],tt[1000001],k,d[1000001],dd[1000001];
struct node
{
long long to,next,x;//to表示这个儿子是谁(GJY) next表示下一个儿子的位置 x表示父亲到当前儿子的边的距离(值)
}e1[2000001],e2[2000001];
queue<long long>q;
bool in[1000001];//判断是否走过
int main()
{
memset(d, 0x7f, sizeof(d));
memset(dd, 0x7f, sizeof(dd));
scanf("%lld%lld",&n,&m);
p = 1;//初始值
for(long long i = 1;i <= m;++i)
{
scanf("%lld%lld%lld",&u,&v,&w);
e1[++k] = (node){v, t[u], w}; //把边的值赋
t[u] = k;
e2[k] = (node){u, tt[v], w}; //同上
tt[v] = k;
}
q.push(p);//起点插入队列
in[p] = 1;//记录到过这个点
d[p] = 0;//距离
while(!q.empty())//还有下一个点可以走
{
long long now = q.front();//现在在那个点
q.pop();//把这个点弹出去
for (long long i = t[now]; i; i = e1[i].next)//枚举它所有到的点
{
long long y = e1[i].to;//到它的下一个点
if (d[now] + e1[i].x < d[y])//判断哪个距离短
{
d[y] = d[now] + e1[i].x;//如果更短,就更新值
if (!in[y])//如果没有到过这个点(避免死循环)
{
in[y] = 1;//标记它走过
q.push(y);//插入点继续走
}
}
}
in[now] = 0;//把不在路径上的点的标记清除
}
q.push(p);//下面是反过来的SPFA
in[p] = 1;
dd[p] = 0;
while(!q.empty())
{
long long now = q.front();
q.pop();
for (long long i = tt[now]; i; i = e2[i].next)
{
long long y = e2[i].to;
if (dd[now] + e2[i].x < dd[y])
{
dd[y] = dd[now] + e2[i].x;
if (!in[y])
{
in[y] = 1;
q.push(y);
}
}
}
in[now] = 0;
}
for(long long i = 1;i <= n; ++i)//因为两边SPFA求出来的都是最优的,所以相加即可
if(i != p) ans += d[i] + dd[i];
printf("%lld",ans);
return 0;
}