luogu P1342 请柬

dij板子的灵活运用

在一个有向图中求:1.1号点到剩下所有点的最短路 2.剩下所有点到一号点的最短路

1相信谁都会,存有向图跑一遍

2是这道题的精髓,应用一个比较有价值的思想:在有向图中跑反向边,相当于求出所有点到一号点的最短路

所以简单说就是存两个版本的图然后两遍dij板子

#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#define ll long long
#define re register
#define il inline
#define inf 214748364
#define fp(i,a,b) for(re int i=a;i<=b;i++)
#define fq(i,a,b) for(re int i=a;i>=b;i--)
using namespace std;
int n,m,h[1000005],cnt=0,inq[1000005]={},dis[1000005]={},h1[1000005]={};
ll ans=0;
struct Edge
{
    int to,next,w;
}e[1000005],e1[1000005];
struct Node
{
    int l,d;
    Node(){}
    Node(int l,int d):l(l),d(d){}
    bool operator < (const Node& zsy) const
        {
            return l>zsy.l;
        }
};
il void add(re int u,re int v,re int w)
{
    e[++cnt]=(Edge){v,h[u],w};h[u]=cnt;
}
il void add1(re int u,re int v,re int w)
{
    e1[cnt]=(Edge){v,h1[u],w};h1[u]=cnt;
}
il void Dijkstra()
{
    fp(i,1,n) dis[i]=inf;
    dis[1]=0;
    priority_queue<Node>Q;
    Q.push(Node(0,1));
    while(!Q.empty())
    {
        Node u=Q.top();Q.pop();
        if(inq[u.d]) continue;
        inq[u.d]=1;
        for(re int i=h[u.d];i+1;i=e[i].next)
        {
            re int v=e[i].to,w=e[i].w;
            if(u.l+w<dis[v])
            {
                dis[v]=u.l+w;
                Q.push(Node(dis[v],v));
            }
        }
    }
}
il void Dijkstra1()
{
    fp(i,1,n) dis[i]=inf;
    dis[1]=0;
    memset(inq,0,sizeof(inq));
    priority_queue<Node>Q;
    Q.push(Node(0,1));
    while(!Q.empty())
    {
        Node u=Q.top();Q.pop();
        if(inq[u.d]) continue;
        inq[u.d]=1;
        for(re int i=h1[u.d];i+1;i=e1[i].next)
        {
            re int v=e1[i].to,w=e1[i].w;
            if(u.l+w<dis[v])
            {
                dis[v]=u.l+w;
                Q.push(Node(dis[v],v));
            }
        }
    }
}
int main()
{
    memset(h,-1,sizeof(h));memset(h1,-1,sizeof(h1));
    scanf("%lld%lld",&n,&m);
    fp(i,1,m)
    {
        ll u,v,w;
        scanf("%lld%lld%lld",&u,&v,&w);
        add(u,v,w);
        add1(v,u,w);
    }
    Dijkstra();
    fp(i,2,n) ans+=dis[i];
    Dijkstra1();
    fp(i,2,n) ans+=dis[i];
    printf("%lld\n",ans);
    return 0;
}

原文地址:https://www.cnblogs.com/charlesss/p/10742547.html

时间: 2024-11-11 05:43:51

luogu P1342 请柬的相关文章

Luogu P1342 请柬 题解

差不多是Dijkstra的裸题吧... 这道题可以分为来回两个阶段. 去的时候很简单,直接用一次Dijkstra,然后统计答案. 回来的时候就有些巧妙了,虽然表面上是每个点回到起点,但是何尝不可将其看成从起点出发,逆着每个点过来的路去找一次每个点?所以只需要存边的时候处理一下,然后直接跑Dijkstra就行了. 附上代码. #include<bits/stdc++.h> #define clean(a,i) memset(a,i,sizeof(a)) #define ll long long

洛谷 P1342 请柬

P1342 请柬 题目描述 在电视时代,没有多少人观看戏剧表演.Malidinesia古董喜剧演员意识到这一事实,他们想宣传剧院,尤其是古色古香的喜剧片.他们已经打印请帖和所有必要的信息和计划.许多学生被雇来分发这些请柬.每个学生志愿者被指定一个确切的公共汽车站,他或她将留在那里一整天,邀请人们参与. 这里的公交系统是非常特殊的:所有的线路都是单向的,连接两个站点.公共汽车离开起始点,到达目的地之后又空车返回起始点.学生每天早上从总部出发,乘公交车到一个预定的站点邀请乘客.每个站点都被安排了一名

洛谷—— P1342 请柬

https://www.luogu.org/problemnew/show/1342 题目描述 在电视时代,没有多少人观看戏剧表演.Malidinesia古董喜剧演员意识到这一事实,他们想宣传剧院,尤其是古色古香的喜剧片.他们已经打印请帖和所有必要的信息和计划.许多学生被雇来分发这些请柬.每个学生志愿者被指定一个确切的公共汽车站,他或她将留在那里一整天,邀请人们参与. 这里的公交系统是非常特殊的:所有的线路都是单向的,连接两个站点.公共汽车离开起始点,到达目的地之后又空车返回起始点.学生每天早上

P1342 请柬

题目描述 在电视时代,没有多少人观看戏剧表演.Malidinesia古董喜剧演员意识到这一事实,他们想宣传剧院,尤其是古色古香的喜剧片.他们已经打印请帖和所有必要的信息和计划.许多学生被雇来分发这些请柬.每个学生志愿者被指定一个确切的公共汽车站,他或她将留在那里一整天,邀请人们参与. 这里的公交系统是非常特殊的:所有的线路都是单向的,连接两个站点.公共汽车离开起始点,到达目的地之后又空车返回起始点.学生每天早上从总部出发,乘公交车到一个预定的站点邀请乘客.每个站点都被安排了一名学生.在一天结束的

[洛谷P1342]请柬

题目大意:有n个站,和m条单向边,每条边有乘车价值,保证汽车能开回来.有n-1个学生从1出发,分别到n-1个不同的点,然后回来.求最少的总价值. 解题思路:最短路,求回来的最少价值其实可以建立反向图,然后跑最短路即可.一共两遍最短路,我用堆优化Dijkstra算法,时间复杂度$O(m\log n)$. 注意long long. pbds大法好! C++ Code: #include<ext/pb_ds/priority_queue.hpp> #include<cstdio> #in

P1342 请柬 建反图+dijkstra

题目链接 一句话题意:喊你求出从1出发到所有点的最短路以及所有点的最短路到1的最短路之和. 从1开始跑最短路很容易,直接一遍堆优化dijkstra就完了. 对于其他点到1的最短路又怎么求,不可能一个一个的求,所以想到之前暑假讲关于图论的技巧——建反图. 这样的话问题就迎刃而解了,再在反图上从1开始跑一遍最短路就完了. 代码如下: #include<bits/stdc++.h> using namespace std; const int maxn=2e6+7; const int inf=0x

BZOJ4277:萃香的请柬——题解

https://www.luogu.org/problemnew/show/P4277 萃香在小时候就一直有一个梦想,就是邀请全乡居民一起参加宴会,在上次发动异变被灵梦退治之后她仍旧没有放弃,而是在元宵节前早早准备好了难以计数的请柬. 现在,宴会即将开始,萃香却还是有一大堆请柬没有送出.经过大数学家琪露诺的严谨推算,到2018年时幻想乡的居民数目已经远远超过了外界,而这就使得宴会的邀请变得极为困难. 但是,拥有"操纵密度程度的能力"的萃香可以分成大大小小的萃香一起去送请柬.由于小萃香的

luogu P3799 妖梦拼木棒

二次联通门 : luogu P3799 妖梦拼木棒 /* luogu P3799 妖梦拼木棒 用一个桶存下所有的木棒 美剧两根短的木棒长度 后随便乘一乘就 好了.. */ #include <algorithm> #include <cstdio> #define Mod 1000000007 #define Max 5000 void read (int &now) { now = 0; register char word = getchar (); while (wo

[luogu P1967][NOIp2013]P1967 货车运输

题目描述 A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 q 辆货车在运输货物, 司机们想知道每辆车在不超过车辆限重的情况下,最多能运多重的货物. 输入输出格式 输入格式: 输入文件名为 truck.in. 输入文件第一行有两个用一个空格隔开的整数 n,m,表示 A 国有 n 座城市和 m 条道 路. 接下来 m 行每行 3 个整数 x. y. z,每两个整数之间用一个空格隔开,表示从 x 号城市到 y 号城市有一条限重为 z