洛谷!P1186!

有关毒瘤 · 洛谷 · 玛丽卡

一、题目描述

在这里插入图片描述

话说麦克找新女朋友管我P事

二、输入输出

在这里插入图片描述
输出一个最长的时间,我们还可以了解玛丽卡走的是当前条件下的最短路径

输入 :题面可知麦克在1号点,玛丽卡在n号点

三、最基础的分析

-----------------------------------------下面我将用画图来为大家解读-----------------------------------------

样例的图如下:

在这里插入图片描述

我们根据题意已知麦克在1号点,玛丽卡在n号点,并且图为无向图

显然:当前的最短路径为5 => 2 => 1 时间总和为1 + 8 = 9

当然,那么当5 => 2堵车了,怎么办呢?

也就是说5 => 2这条边不存在了,这时候的图转变为:

在这里插入图片描述
显然:当前的最短路径有两条:

分别是:5 => 3 => 4 => 15 => 3 => 2 => 1

时间总和分别为:10 + 7 + 10 = 27 和 10 + 9 + 8 = 27

       是不是看到这里觉得就可以停止了呢,其实不然,到此为止只切割了首次最短路径的其中一条边,事实上需要将每一条边都切割掉再进行寻找最短路径。

于是又会出现一种图:

在这里插入图片描述
显然:此时的最短路径也有两条:

分别是:5 => 2 => 4 => 15 => 3 => 4 => 1

时间总和分别为:1 + 10 + 10 = 21 和 10 + 7 + 10 = 27

到此为止,该情况才结束。

      综合上述分析:

第一步操作:找到完整图并且找到最短路记录时间与max = 0比较,并记录每一条边的编号

第二步操作:将记录下的边依次删去后再次寻找最短路并记录时间取最大值

最后一步操作:输出最大的时间

四、算法实现

SPFA算法:

      代码实现:

#include<cstdio>
#include<queue>
#include<cstring>
#include<vector>
const int maxn = 1001;
const int maxm = 499501;
const int inf = 0x3f3f3f3f;
using namespace std;
struct edge{
	int next;
	int to;
	int w;
}e[4995010];
int head[maxn];
int ecnt;
int n,m;	
void Init(){   													//初始化 
	for(int i = 0 ; i < maxm ; i++) e[i].next = 0;
	for(int i = 0 ; i < maxn ; i++) head[i] = 0;
	ecnt = 0;
}
void addedge(int u,int v,int w){
	e[++ecnt] = (edge){head[u],v,w};
	head[u] = ecnt;
}
void Insert(int x){
	for(int i = 1 ; i <= x ; i ++){
		int u,v,w;
		scanf("%d %d %d",&u,&v,&w);
		addedge(u,v,w);
		addedge(v,u,w);
	}
}
int dis[maxn],cnt1[maxn],cnt2[maxn];
int CUT[1005][1005],f[1001];
int Ans = 0;
int flag;
bool vis[maxn];
void SPFA(){
	queue<int> Q;
	memset(dis,0x3f,sizeof(dis));
	memset(vis,0,sizeof(vis));
	dis[1] = 0; 
	vis[1] = true;
	Q.push(1);	
	while(!Q.empty()){
		int x = Q.front();Q.pop();								//立即弹出 
		vis[x] = false;
		for(int i = head[x] ; i ; i = e[i].next){
			if(CUT[x][e[i].to] == 0 &&  dis[e[i].to] > dis[x] + e[i].w){
				if(!flag)f[e[i].to] = x;
				int y = e[i].to , z = e[i].w;
				dis[y] = dis[x] + z;  
				if(!vis[e[i].to]){
					vis[e[i].to] = true;
					Q.push(e[i].to); 
				}
			}
		}
	}
	return;
}
int main(){
	scanf("%d %d",&n,&m);
	Insert(m);
	SPFA();
	flag = 1;
	for(int i = n ; i != 1 ; i = f[i]){
        CUT[f[i]][i] = 1;
        CUT[i][f[i]] = 1;
        SPFA();
        CUT[f[i]][i] = 0;
        CUT[i][f[i]] = 0;
        Ans = Ans > dis[n] ? Ans:dis[n];
    }
    printf("%d",Ans);
	return 0;
} 

迪杰克斯拉算法:
      代码实现:

#include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<cctype>
#include<vector>
#include<queue>
#include<assert.h>
#include<ctime>
using namespace std;
#define enter puts("") 
#define space putchar(' ')
#define Mem(a, x) memset(a, x, sizeof(a))
#define In inline
#define forE(i, x, y) for(int i = head[x], y; ~i && (y = e[i].to); i = e[i].nxt)
typedef long long ll;
typedef double db;
const int INF = 0x3f3f3f3f;
const db eps = 1e-8;
const int maxn = 1e3 + 5;
In ll read()
{
	ll ans = 0;
	char ch = getchar(), last = ' ';
	while(!isdigit(ch)) last = ch, ch = getchar();
	while(isdigit(ch)) ans = (ans << 1) + (ans << 3) + ch - '0', ch = getchar();
	if(last == '-') ans = -ans;
	return ans;
}
In void write(ll x)
{
	if(x < 0) x = -x, putchar('-');
	if(x >= 10) write(x / 10);
	putchar(x % 10 + '0');
}

int n, m, c[maxn][maxn];

#define pr pair<int, int>
#define mp make_pair
int dis[maxn], pre[maxn];
bool vis[maxn];
priority_queue<pr, vector<pr>, greater<pr> > q;
In void dijkstra(int s, bool flg)
{
	for(int i = 1; i <= n; ++i) dis[i] = INF, vis[i] = 0;
	dis[s] = 0;
	q.push(mp(0, s));
	while(!q.empty())
	{
		int now = q.top().second; q.pop();
		if(vis[now]) continue;
		vis[now] = 1;
		for(int i = 1; i <= n; ++i)
			if(c[now][i])
			{
				if(dis[i] > dis[now] + c[now][i])
				{
					if(flg) pre[i] = now;
					dis[i] = dis[now] + c[now][i];
					q.push(mp(dis[i], i));
				}
			}
	}
}

int main()
{
//	MYFILE();
	n = read(), m = read();
	for(int i = 1; i <= m; ++i)
	{
		int x = read(), y = read(), w = read();
		c[x][y] = c[y][x] = w;
	}
	dijkstra(1, 1);
	int ans = 0;
	for(int i = n; i > 1; i = pre[i])
	{
		int tp = c[i][pre[i]];
		c[i][pre[i]] = c[pre[i]][i] = 0;
		dijkstra(1, 0);
		ans = max(ans, dis[n]);
		c[i][pre[i]] = c[pre[i]][i] = tp;
	}
	write(ans), enter;
	return 0;	//此代码引用MRCLR学长
}

最后:

      有关毒瘤数据开启O2优化可能会过,问题正在解决中……

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值