poj---3268---Silver Cow Party(最短路)

3268---Silver Cow Party

题目

在这里插入图片描述
在这里插入图片描述

思路

这道题相对来说比较简单,我用的是堆优化的dijkstra算法,就是用优先队列来代替了每次找最小路径的循环,减小了时间复杂度,这道题首先我们可以先计算每头牛从X点回自己的起点时的最短路,记录下来成一个数组,然后将邻接矩阵转置(邻接表的话就重新构造一个邻接表),这里的转置相当于将每条边的方向反过来,这样的话再计算一下每头牛从X点回自己的起点时的最短路,就相当于没调换边的方向时,每头牛从自己的起点出发到X的最短路,所以,就把两个求出来的数组对应求和,得到和数组,找其中的最大值就可以了,这里的转置技巧还是很常用的。

题解

#include <iostream>
#include <cstring>
#include <stdio.h>
#include <algorithm>
#include <vector>
#include <queue>
using namespace std;
const int INF=0x3f3f3f3f;
const int MAXN=1000100;
struct qnode{
	int v;
	int c;
	qnode(int _v=0,int _c=0):v(_v),c(_c){}
	bool operator <(const qnode &r)const{
		return c>r.c;
	}
};
struct Edge{
	int v,cost;
	Edge(int _v=0,int _cost=0):v(_v),cost(_cost){}
};
vector<Edge>E1[MAXN];
vector<Edge>E2[MAXN];
bool vis[MAXN];
int dist[MAXN];
//点的编号从 1 开始
void Dijkstra(int n,int start,vector<Edge>E[MAXN]){
	memset(vis,false,sizeof(vis));
	for(int i=1;i<=n;i++)dist[i]=INF;
	priority_queue<qnode>que;
	while(!que.empty())que.pop();
	dist[start]=0;
	que.push(qnode(start,0));
	qnode tmp;
	while(!que.empty()){
		tmp=que.top();
		que.pop();
		int u=tmp.v;
		if(vis[u])continue;
		vis[u]=true;
		for(int i=0;i<E[u].size();i++){
			int v=E[tmp.v][i].v;
			int cost=E[u][i].cost;
			if(!vis[v]&&dist[v]>dist[u]+cost){
				dist[v]=dist[u]+cost;
				que.push(qnode(v,dist[v]));
			}
		}
	}
}
void addedge(int u,int v,int w,vector<Edge>E[MAXN]){
	E[u].push_back(Edge(v,w));
}
int main()
{
	int n,m,x;
	cin>>n>>m>>x;
	int lu1[n+1][n+1];
	int lu2[n+1][n+1];
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			if(i==j)
			{
				lu1[i][j]=0;
				lu2[i][j]=0;
				continue;
			}
			lu1[i][j]=-1;
			lu2[i][j]=-1;
		}
	}
	for(int i=0;i<m;i++)
	{
		int v,u,w;
		cin>>v>>u>>w;
		lu1[v][u]=w;
		lu2[u][v]=w;
	} 
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			if(lu1[i][j]!=0&&lu1[i][j]!=-1)
			{
				addedge(i,j,lu1[i][j],E1);
			}
		}
	}
	Dijkstra(n,x,E1);
	int ans=0;
	int max_n[n+1];
	memset(max_n,0,sizeof(max_n));
	for(int i=1;i<=n;i++)
	{
		max_n[i]=dist[i];
	}
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			if(lu2[i][j]!=0&&lu2[i][j]!=-1)
			{
				addedge(i,j,lu2[i][j],E2);
			}
		}
	}
	Dijkstra(n,x,E2);
	for(int i=1;i<=n;i++)
	{
		if(ans<max_n[i]+dist[i])
		{
			ans=max_n[i]+dist[i];
		}
	}
	cout<<ans<<endl;
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

初见。。

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值