请柬

    技术2024-07-19  76

    请 柬 请柬

    题目链接: l u o g u   1342 luogu\ 1342 luogu 1342

    题目背景

    在电视时代,没有多少人观看戏剧表演。 Malidinesia 古董喜剧演员意识到这一事实,他们想宣传剧院,尤其是古色古香的喜剧片。

    题目

    他们已经打印了请帖和所有必要的信息和计划。许多学生被雇来分发这些请柬。每个学生志愿者被指定一个确切的公共汽车站,他或她将留在那里一整天,邀请人们参与。

    这里的公交系统是非常特殊的:共有 n n n 个站点和 m m m 个线路,所有的线路都是单向的,连接两个站点。公共汽车离开起始点,到达目的地之后又空车返回起始点。

    学生每天早上从总部所在的 1 1 1 号站点出发,乘公交车到一个预定的站点邀请乘客。每个站点都被安排了一名学生。在一天结束的时候,所有的学生都回到总部。现在需要知道的是,学生所需的公交费用的总和最小是多少。

    输入

    输入的第一行是两个整数,代表站点个数 n n n 和线路条数 m m m

    2 2 2 到第 ( m  ⁣ +  ⁣ 1 ) (m\! +\! 1) (m+1) 行,每行三个整数 u , v , w u, v, w u,v,w,代表存在一条从 u u u 出发到达 v v v 的线路,费用为 w w w

    输出

    输出一行一个整数,表示最小费用。

    样例输入

    4 6 1 2 10 2 1 60 1 3 20 3 4 10 2 4 5 4 1 50

    样例输出

    210

    数据范围

    对于 100 % 100\% 100% 的数据,保证:

    1 ≤ n , m ≤ 1 0 6 1 \leq n, m \leq 10^6 1n,m106 1 ≤ u , v ≤ n 1 \leq u, v \leq n 1u,vn 1 ≤ w ≤ 1 0 9 1 \leq w \leq 10^9 1w109。 从 1 1 1 出发可以到达所有的站点。

    思路

    这道题和邮递员送信很像,起点也是都在 1 1 1号点。

    不过不同的地方就是数据范围变大了,但是无所谓,这种方法可以过,把数据范围开大一点就可以了。 有一点要注意的是,我们要开 l o n g   l o n g long\ long long long

    代码

    #include<queue> #include<cstdio> #include<cstring> #include<iostream> #define ll long long using namespace std; struct node{ ll to, next, x; }e1[10000001], e2[10000001]; ll n, m, p, x, y, z, ans, le1[1000001], le2[1000001], k, dis1[1000001], dis2[1000001]; bool in[1000001]; queue<ll>q; int main() { memset(dis1, 0x7f, sizeof(dis1));//初始化 memset(dis2, 0x7f, sizeof(dis2)); scanf("%lld %lld", &n, &m);//读入 p = 1; for (ll i = 1; i <= m; i++) { scanf("%lld %lld %lld", &x, &y, &z);//读入 e1[++k] = (node){y, le1[x], z}; le1[x] = k;//建图 e2[k] = (node){x, le2[y], z}; le2[y] = k;//反方向建图 } q.push(p); in[p] = 1; dis1[p] = 0; while (!q.empty()) {//正向spfa ll now = q.front(); q.pop(); for (ll i = le1[now]; i; i = e1[i].next) { ll y = e1[i].to; if (dis1[now] + e1[i].x < dis1[y]) { dis1[y] = dis1[now] + e1[i].x; if (!in[y]) { in[y] = 1; q.push(y); } } } in[now] = 0; } q.push(p); in[p] = 1; dis2[p] = 0; while (!q.empty()) {//反向spfa ll now = q.front(); q.pop(); for (ll i = le2[now]; i; i = e2[i].next) { ll y = e2[i].to; if (dis2[now] + e2[i].x < dis2[y]) { dis2[y] = dis2[now] + e2[i].x; if (!in[y]) { in[y] = 1; q.push(y); } } } in[now] = 0; } for (ll i = 1; i <= n; i++) if (i != p) ans += dis1[i] + dis2[i];//找到路径最长的一个点 printf("%lld", ans);//输出 return 0; }
    Processed: 0.019, SQL: 9