2021 RoboCom 世界机器人开发者大赛-本科组(决赛)7-4猛犸不上 Ban(最短路)

 样例输入:

5 6 1 5
1 2 1
2 3 2
3 4 3
4 1 5
3 5 4
4 5 1

样例输出:

11 6
Lose!

分析:对于第二种选择显然直接跑一边最短路就可以了,这里就不多说了,下面主要说一下第一种选择。我一开始以为直接跑一个最短路就行,对于第一种说的回到s点,直接枚举与s存在直接边的j,求一个min(d[j]+dis[j][s])即可,但是发现样例都不对,模拟了一下发现存在重边,也就是说从s到j求最短路时经过了直接边s->j,所以就会产生错误,然后就发现思路错了,我就尝试了一下跑多次最短路,也就是对于每一个和s有直接边的j,我都直接跑一边最短路,但是这次最短路不能经过s->j这条边,然后我们再求一下d[j]+dis[j][s],最后取一个最小值即可。交了之后有一个超时,但是看了一下边数和点数,边数是1e5,点数是500,因为我写的是堆优化版的dijkstra,复杂度是O(mlogm),而这道题给的是一个稠密图,所以最好是用朴素版的最短路,直接换成朴素版的就能过了。复杂度是O(n^3)

细节见代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<map>
#include<queue>
#include<vector>
#include<cmath>
using namespace std;
const int N=1e6+10;
typedef pair<int,int>PII;
int d[N],n;
int p[503][503];
bool vis[N];
void dijkstra(int x,int u,int v)
{
	memset(vis,false,sizeof vis);
	memset(d,0x3f,sizeof d);
	d[x]=0;
	for(int i=1;i<n;i++)
	{
		int t=-1;
		for(int j=1;j<=n;j++)
			if(!vis[j]&&(t==-1||d[t]>d[j])) t=j;
		vis[t]=true;
		for(int j=1;j<=n;j++)
		{
			if(t==u&&j==v) continue;
			if(d[j]>d[t]+p[t][j]) d[j]=d[t]+p[t][j];
		}
	}
}
int main()
{
	int m,s,t;
	cin>>n>>m>>s>>t;
	memset(p,0x3f,sizeof p);
	for(int i=1;i<=m;i++)
	{
		int u,v,t;
		scanf("%d%d%d",&u,&v,&t);
		p[u][v]=p[v][u]=t;
	}
	int t1=0x3f3f3f3f;
	for(int i=1;i<=n;i++)
	{
		if(i==s||p[i][s]==0x3f3f3f3f) continue;
		dijkstra(s,s,i);
		t1=min(t1,d[i]+p[i][s]);
	}
	dijkstra(s,0,0);
	int t2=d[t];
	if(t1==0x3f3f3f3f) printf("-1 ");
	else printf("%d ",t1);
	if(t2==0x3f3f3f3f) printf("-1\n");
	else printf("%d\n",t2);
	if(t1!=0x3f3f3f3f&&t1<t2) printf("Win!");
	else printf("Lose!");
	return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值