次短路

单源(即从顶点s到顶点t的最短路):

问题链接: 

 https://loj.ac/p/10076

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+5,inf=0x3f3f3f3f;
int nxt[N],to[N],dis[N];
int head[5005];
int n,m,x,tot;
int d2[5005],d1[5005];
int ans;
struct dd
{
	int p;
	int val;
	bool operator < (const dd &t)const
	{
		return t.val<val;
	}
}t1;
priority_queue<dd>q;
void add(int x,int y,int z)
{
	dis[++tot]=z;
	to[tot]=y;
	nxt[tot]=head[x];
	head[x]=tot;
}
int Dijkstra(int s,int t)
{
	for(int i=1; i<=n; i++)
		d2[i]=d1[i]=inf;
	d2[s]=0;
	q.push((dd){s,0});//优先队列
	while(!q.empty())
	{
		t1=q.top();
		q.pop();
		for(int i=head[t1.p];i; i=nxt[i])
		{
			if(d2[to[i]]>t1.val+dis[i])//d2记录最短路,d1记录次短路
			{
				d1[to[i]]=d2[to[i]];
				d2[to[i]]=t1.val+dis[i];
				q.push((dd){to[i],d2[to[i]]});
			}
			else if(d1[to[i]]>t1.val+dis[i]&&d2[to[i]]<t1.val+dis[i])
			{
				d1[to[i]]=t1.val+dis[i];
				q.push((dd){to[i],d1[to[i]]});
			}
		}
	}
	return d1[t];
}
int main()
{
	int u,v,w;
	cin>>n>>m;
	for(int i=1; i<=m; i++)
	{
		scanf("%d%d%d",&u,&v,&w);
		add(u,v,w);
		add(v,u,w);
	}
	printf("%d\n",Dijkstra(1,n));
	return 0;
}

次短路全连通:

问题链接

https://loj.ac/p/10068

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e5 + 7;
int n, m;
int ne[N], head[N], e[N], w[N], cnt, dis1[505][505], dis2[505][505], pre[N], sum;
struct Node
{
	int u, v, cost;
	bool lef;
	bool operator< (const Node &b)const
	{
		return cost < b.cost;
	}
} node[N];
void add(int a, int b, int c)
{
	e[cnt] = b;
	ne[cnt] = head[a];
	w[cnt] = c;
	head[a] = cnt++;
}
int find(int x)
{
	if (x != pre[x])
		return pre[x] = find(pre[x]);
	return pre[x];
}
void kru()
{
	for (int i = 0; i < m; i++)
	{
		int u = node[i].u, v = node[i].v, cost = node[i].cost;
		int fx = find(u);
		int fy = find(v);
		if (fx != fy)
		{
			node[i].lef = 1;
			pre[fy] = fx;
			sum += cost;
			add(u, v, cost), add(v, u, cost);
		}
	}
}
void dfs(int u, int last, int maxd1, int maxd2, int x)//maxd1,maxs2 记录从x到u的最大一段路
{                                                     //与次大一段路
	dis1[x][u] = maxd1;
	dis2[x][u] = maxd2;
	for (int i = head[u]; i != -1; i = ne[i])
	{
		int j = e[i];
		if (j == last)
			continue;
		int td1 = maxd1, td2 = maxd2;
		if (w[i] > td1)
			td2 = td1, td1 = w[i];
		else if (w[i] > td2)
			td2 = w[i];
		dfs(j, u, td1, td2, x);
	}
}
signed main()
{
	cin >> n >> m;
	memset(head, -1, sizeof head);
	for (int i = 1; i <= n; i++)
		pre[i] = i;
	for (int i = 0; i < m; i++)
	{
		int a, b, c;
		cin >> a >> b >> c;
		node[i].u = a, node[i].v = b, node[i].cost = c;
		node[i].lef = 0;
	}
	sort(node, node + m);
	sum = 0;
	kru();
	for (int i = 1; i <= n; i++)
		dfs(i, -1, 0, 0, i);
	int res = 1e18;
	for (int i = 0; i < m; i++)
		if (!node[i].lef)
		{
			int a = node[i].u, b = node[i].v, c = node[i].cost;
			if (c > dis1[a][b])	res = min(res, sum + c - dis1[a][b]);
			else if (c > dis2[a][b])	res = min(res, sum + c - dis2[a][b]);
		}
	cout << res << endl;
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值