Luogu P1342 请柬 题解

差不多是Dijkstra的裸题吧。。。

  • 这道题可以分为来回两个阶段。
  • 去的时候很简单,直接用一次Dijkstra,然后统计答案。
  • 回来的时候就有些巧妙了,虽然表面上是每个点回到起点,但是何尝不可将其看成从起点出发,逆着每个点过来的路去找一次每个点?所以只需要存边的时候处理一下,然后直接跑Dijkstra就行了。
  • 附上代码。
#include<bits/stdc++.h>
#define clean(a,i) memset(a,i,sizeof(a))
#define ll long long
#define inl inline
#define il inl void
#define it inl int
#define ill inl ll
#define re register
#define ri re int
#define rl re ll
using namespace std;
template<class T>il read(T &x)
{
    int f=1;char k=getchar();x=0;
    for(;k>'9'||k<'0';k=getchar()) if(k=='-') f=-1;
    for(;k>='0'&&k<='9';k=getchar()) x=(x<<3)+(x<<1)+k-'0';
    x*=f;
}
const int MAXN = 1e6+5;
int n,m,u,v,d,head[MAXN],num_edge,dis[MAXN];
ll ans;
struct Edge{
    int next,to,dis,type; //存边的时候用了一个type标记,1表示它为正向边,2表示它为反向边
    Edge(){}
    Edge(int next,int to,int dis,int type):next(next),to(to),dis(dis),type(type){}
}edge[MAXN<<1];
il add_edge(int u,int v,int dis){
    edge[++num_edge]=Edge(head[u],v,dis,1);head[u]=num_edge; //加正边
    edge[++num_edge]=Edge(head[v],u,dis,2);head[v]=num_edge; //加反边
}
struct Node{
    int pos,dis;
    Node(){}
    Node(int pos,int dis):pos(pos),dis(dis){}
    bool operator <(const Node &t) const{
        return dis>t.dis;
    }
};
bool tr[MAXN];
il dijkstra(int type){
    priority_queue<Node> q;q.push(Node(1,0));
    for(ri i=2;i<=n;i++) dis[i]=2147483647;
    clean(tr,0);
    while(!q.empty()){
        Node tmp=q.top();q.pop();
        ri pos=tmp.pos;
        if(tr[pos]) continue;
        tr[pos]=true;
        for(ri i=head[pos];i;i=edge[i].next){
            if(edge[i].type!=type) continue; //进行判断
            if(dis[edge[i].to]>dis[pos]+edge[i].dis){
                dis[edge[i].to]=dis[pos]+edge[i].dis;
                if(!tr[edge[i].to]) q.push(Node(edge[i].to,dis[edge[i].to]));
            }
        }
    }
    for(ri i=2;i<=n;i++) ans+=dis[i]; //统计答案
}
int main()
{
//  freopen(".in","r",stdin);
//  freopen(".out","w",stdout);
    read(n),read(m);
    for(ri i=1;i<=m;i++) read(u),read(v),read(d),add_edge(u,v,d);
    dijkstra(1);dijkstra(2);
    printf("%lld",ans); //答案记得开long long
    return 0;
}
  • 这道题其实更优的方法是开两个结构体,分别来存正反边,这样时间复杂度会小一些(毕竟不用每条边正反两个每次都要跑),但是为什么我没有这样写呢?当然是我懒啊
  • OK,完工。[]~( ̄▽ ̄)~*

原文地址:https://www.cnblogs.com/TheShadow/p/10660171.html

时间: 2024-11-10 15:58:17

Luogu P1342 请柬 题解的相关文章

luogu P1342 请柬

dij板子的灵活运用 在一个有向图中求:1.1号点到剩下所有点的最短路 2.剩下所有点到一号点的最短路 1相信谁都会,存有向图跑一遍 2是这道题的精髓,应用一个比较有价值的思想:在有向图中跑反向边,相当于求出所有点到一号点的最短路 所以简单说就是存两个版本的图然后两遍dij板子 #include<cmath> #include<cstdio> #include<cstring> #include<algorithm> #include<queue>

洛谷 P1342 请柬

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

BZOJ4277:萃香的请柬——题解

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

洛谷—— P1342 请柬

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

P1342 请柬

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

Luogu P4014 分配问题 题解

闲扯 蒟蒻的第一道自己想出怎么建图的题!!虽然是一个没什么技术含量的图 想了想,还是写篇题解纪念一下. 题面 题面 Solution 要求最小费用和最大费用,同时限制了流量,考虑费用流. 虚拟一个超级源点,从这个点分别向 \(N\) 个任务连一条流量为 \(1\) ,费用为 \(0\) 的边. 虚拟一个超级汇点,才从 \(N\) 个物品分别向该点连一条流量为 \(1\) ,费用为 \(0\) 的边. 因为每个人只能做一件,且每个工作只能做一次,所以连的边流量都为一.而第 \(i\) 个人做第 \

[洛谷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

邮递员送信(luogu 1629)题解

[问题描述] 有一个邮递员要送东西,邮局在节点1.他总共要送N-1样东西,其目的地分别是2~N.由于这个城市的交通比较繁忙,因此所有的道路都是单行的,共有M条道路,通过每条道路需要一定的时间.这个邮递员每次只能带一样东西.求送完这N-1样东西并且最终回到邮局最少需要多少时间. [样例输入] 5 10    2 3 5    1 5 5    3 5 6    1 2 8    1 3 8    5 3 4    4 1 8    4 5 3    3 5 6    5 4 2 [样例输出] 83

$Luogu P2029$ 跳舞 题解

一道不是十分水的\(dp\). 首先我们考虑\(dp\)方程的构造.起初我定义的状态是\(dp_{i,j}\)表示前\(i\)个格子,总共跳了\(j\)次的最大得分.但事实上它并不可以转移,因为我们不知道新的一轮操作从之间的哪个格子算起. 那么状态转移方程就出来了,我们把第一维改成本次跳到第\(i\)个格子上,包括本次在内总共跳了\(j\)次的最大得分,那么转移的时候,由于本次一定要跳到\(i\)上(如状态中所定义),所以不用分类讨论.方程就是:\[dp_{i,j}=\max\{dp_{k,j-