P1629 邮递员送信(正反向建图 or 暴力)

Posted MangataTS

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P1629 邮递员送信(正反向建图 or 暴力)相关的知识,希望对你有一定的参考价值。

题目链接

https://www.luogu.com.cn/problem/P1629

思路

和农场派对这题一样,我们需要正反向建图,然后跑迪杰斯特拉然后再分别加上 [ 2 , n ] [2,n] [2,n]dis值(因为题目中保证了每个点可达),但是这道题可以直接对每个点跑迪杰斯特拉然后再吸一点氧暴力跑过去

代码

正反向建图

#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
#define INF 0x3f3f3f3f
const int N=2e6+5;//数据范围
struct edge//存储边
	int u,v,w,next;//u为起点,v为终点,w为权值,next为前继
;
edge e[N];
int head[N],dis[N],n,m,s,cnt;//head为链中最上面的,dis表示当前答案,n为点数,m为边数,s为起点,cnt记录当前边的数量
bool vis[N];//vis表示这个点有没有走过
struct node
	int w,to;//w表示累加的权值,to表示到的地方
	bool operator <(const node &x)const//重载“<”号
		return w>x.w;
	
;

void add(int u,int v,int w)
	++cnt;//增加边的数量
	e[cnt].u=u;//存起点
	e[cnt].v=v;//存终点
	e[cnt].w=w;//存权值
	e[cnt].next=head[u];//存前继
	head[u]=cnt;//更新链最上面的序号
//链式前向星(加边)
void Dijkstra()
	dis[s]=0;//起点到自己距离为0
	priority_queue<node>q;//优先队列(堆优化)
	q.push(node0,s);//压入队列
	while(!q.empty())//队列不为空
		node x=q.top();//取出队列第一个元素
		q.pop();//弹出
		int u=x.to;//求出起点
		if(vis[u]) continue;//已去过就不去了
		vis[u]=true;//标记已去过
		for(int i=head[u];i;i=e[i].next)
			int v=e[i].v;//枚举终点
			if(dis[v]>dis[u]+e[i].w)//若中转后更优,就转
				dis[v]=dis[u]+e[i].w;//更新
				q.push(nodedis[v],v);//压入队列
			
		
	

int U[N],V[N],W[N];

void init()
	int l = max(n,m);
	for(int i = 1;i <= l; ++i) 
		head[i] = 0,vis[i] = false;
		dis[i] = INF;
	
	cnt = 0;


int main()
	int u,v,w = 1;
	s = 1;
	scanf("%d%d",&n,&m);//输入
	init();
	for(int i = 1;i <= m;++i)
		scanf("%d%d%d",&U[i],&V[i],&W[i]);
		add(U[i],V[i],W[i]);
	
	
	Dijkstra();//DJ
	long long ans = 0;
	for(int i = 2;i <= n; ++i)
		ans += dis[i];
	
	init();
	for(int i = 1;i <= m;++i)
		add(V[i],U[i],W[i]);
	
	Dijkstra();
	for(int i = 2;i <= n; ++i)
		ans += dis[i];
	
	printf("%lld\\n",ans);
	return 0;



暴力DJ+吸氧

#include<iostream>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
#define N 1005
#define INF 0x3f3f3f3f
#define P pair<int,int> 
int n,m;
struct node
	int cost,to;
;
vector<node> G[N];
int d[N];
void dijikstra(int s)
	memset(d,INF,sizeof d);
	d[s]=0;
	priority_queue<P,vector<P>,greater<P> > que;
	que.push(0,s);
	while(!que.empty())
		P p=que.top();
		que.pop();
		int v=p.second;
		if(d[v]<p.first)
		continue;
		for(int i=0;i<G[v].size();++i)
			node e=G[v][i];
			if(d[e.to]>e.cost+d[v])
				d[e.to]=d[v]+e.cost;
				que.push(d[e.to],e.to);
			
		
	

int main()
	int u,v,w;
	scanf("%d%d",&n,&m);
	for(int i=0;i<m;++i)
		scanf("%d%d%d",&u,&v,&w);
		G[u].push_back(w,v);
	
	dijikstra(1);
	long long sum=0;
	for(int i=2;i<=n;++i)
		sum+=d[i];
	
	for(int i=2;i<=n;++i)
		dijikstra(i);
		sum+=d[1];
	
	printf("%lld\\n",sum);

以上是关于P1629 邮递员送信(正反向建图 or 暴力)的主要内容,如果未能解决你的问题,请参考以下文章

P1629 邮递员送信最短路+反向建图

[题解]洛咕P1629 邮递员送信

P1629 邮递员送信

洛谷 P1629 邮递员送信

P1629 邮递员送信

洛谷—— P1629 邮递员送信