【newSSLOJ1297】GF打Dota【最短路】

本文深入探讨了求解图中两点间最短路径与次短路径的算法实现。通过SPFA算法预计算最短路径,再通过枚举所有边,结合两段最短路径判断次短路径,确保了算法的有效性和准确性。

题目大意:

题目链接:http://10.156.31.134/contestnew.aspx?cid=77 (学校局域网)
求一个图的最短路和次短路。


思路:

最短路就不说了,这里讲讲如何求次短路。
如果我们从点1和点 n n n分别跑最短路,记为 d i s [ 0 ] [ x ] dis[0][x] dis[0][x] d i s [ 1 ] [ x ] dis[1][x] dis[1][x]然后枚举每一条边,它所连接的两个点分别为 u u u v v v,那么只要判断 d i s [ 0 ] [ u ] + e [ i ] . d i s + d i s [ 1 ] [ v ] dis[0][u]+e[i].dis+dis[1][v] dis[0][u]+e[i].dis+dis[1][v]是否不是最短路( d i s [ 0 ] [ n ] dis[0][n] dis[0][n] d i s [ 1 ] [ 1 ] dis[1][1] dis[1][1]),而且尽量小就可以了。
因为最短路和次短路至少有一条边是不同的,所以当我们枚举到那条不在最短路却在次短路上的那一条边时,就会得到次短路了。


代码:

#include <cstdio>
#include <queue>
#include <cstring>
#include <iostream>
using namespace std;

const int N=10010;
const int M=100010;
int n,m,x,y,z,tot,ans,head[N],dis[2][N];
bool vis[N],Lu_Benwei;

struct edge
{
	int from,next,to,dis;
}e[M];

void add(int from,int to,int dis)
{
	e[++tot].to=to;
	e[tot].dis=dis;
	e[tot].from=from;
	e[tot].next=head[from];
	head[from]=tot;
}

void spfa(int S,int x)
{
	memset(vis,0,sizeof(vis));
	queue<int> q;
	q.push(S);
	vis[S]=1;
	dis[x][S]=0;
	while (q.size())
	{
		int u=q.front(),v;
		q.pop();
		vis[u]=0;
		for (int i=head[u];~i;i=e[i].next)
		{
			v=e[i].to;
			if (dis[x][v]>dis[x][u]+e[i].dis)
			{
				dis[x][v]=dis[x][u]+e[i].dis;
				if (!vis[v])
				{
					vis[v]=1;
					q.push(v);
				}
			}
		}
	}
}

int main()
{
	memset(head,-1,sizeof(head));
	scanf("%d%d",&n,&m);
	for (int i=1;i<=m;i++)
	{
		scanf("%d%d%d",&x,&y,&z);
		add(x,y,z);
		add(y,x,z);
	}
	memset(dis,0x3f3f3f3f,sizeof(dis));
	scanf("%d",&Lu_Benwei);  //上香 \|/
	if (!Lu_Benwei)
	{
		spfa(1,0);
		printf("%d\n",dis[0][n]);
	}
	else
	{
		spfa(1,0);
		spfa(n,1);
		ans=2147483647;
		for (int i=1;i<=tot;i++)
		{
			int len=dis[0][e[i].from]+dis[1][e[i].to]+e[i].dis;
			if (len>dis[0][n]&&len<ans) ans=len;
		}
		printf("%d",ans);
	}
	return 0;
}
以下是使用Lingo求解短路问题并加入路径约束的代码: ```lingo model: sets: i /1*10/ j /1*10/ k /1*20/ constraints /1.BE 2.CF 3.DE 4.EG 5.GF/ parameters: c(i,j) / 1 2 3 2 4 1 3 4 2 5, 2 1 3 2 1 4 3 3 3 2, 2 3 1 4 2 5 1 2 4 3, 3 2 4 1 3 2 5 1 4 2, 4 1 2 3 1 4 2 3 2 3, 1 4 5 2 4 1 3 2 2 1, 3 3 1 5 2 3 1 4 3 2, 4 1 2 1 3 2 4 3 1 2, 2 2 4 4 2 1 3 2 2 3, 5 1 3 2 1 4 2 3 1 2 / f(i,j) / 10 30 20 40 60 10 20 10 30 50, 20 10 30 40 10 50 20 30 40 20, 30 20 10 50 40 60 10 30 20 40, 40 30 50 20 10 30 60 10 20 30, 50 10 20 30 20 10 40 30 30 20, 10 50 60 20 50 10 20 30 20 10, 20 40 30 10 30 20 50 20 40 30, 30 10 20 10 20 30 40 30 10 20, 10 20 50 40 30 10 20 30 20 20, 50 10 30 20 10 50 40 30 20 40 / start(i) /1/ end(i) /10/ variables: x(i,j) binary z equations: obj: z = sum((i,j), f(i,j)*x(i,j)) start_con: sum(j, x(start,j)) = 1 end_con: sum(i, x(i,end)) = 1 flow_con(i)$(not sameas(i,start) and not sameas(i,end)): sum(j, x(i,j)) - sum(j, x(j,i)) = 0 arc_con(i,j): x(i,j) + x(j,i) <= 1 subtour_con(k)$(card(k) gt 1): sum((i,j)$(ord(i) lt ord(j) and i in k and j in k), x(i,j)) <= card(k) - 1 path_con(i,j)$(index(constraints, str(i.j)) gt 0): x(i,j) = 0 model_name "ConstrainedShortestPath"; solve; display z, x; ``` 该模型中,`i`和`j`表示图的节点,`k`表示子集,`c(i,j)`表示节点i到节点j的距离,`f(i,j)`表示节点i到节点j的费用,`start(i)`表示起点,`end(i)`表示终点,`x(i,j)`表示是否选择从节点i到节点j的路径,`z`表示小费用。`constraints`表示路径约束,这里包含5个约束路径。模型的约束分别为:起点只有一条出边,终点只有一条入边,流量守恒约束,路径是有向无环图,子集约束,路径约束,目标函数为小费用。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值