洛谷P2176 [USACO14FEB]路障Roadblock(枚举+spfa) 题解

题目来源:

https://www.luogu.org/problemnew/show/P2176

题目描述:

题目描述

每天早晨,FJ从家中穿过农场走到牛棚。农场由 N 块农田组成,农田通过 M 条双向道路连接,每条路有一定长度。FJ 的房子在 1 号田,牛棚在 N 号田。没有两块田被多条道路连接,以适当的路径顺序总是能在农场任意一对田间行走。当FJ从一块田走到另一块时,总是以总路长最短的道路顺序来走。

FJ 的牛呢,总是不安好心,决定干扰他每天早晨的计划。它们在 M 条路的某一条上安放一叠稻草堆,使这条路的长度加倍。牛希望选择一条路干扰使得FJ 从家到牛棚的路长增加最多。它们请你设计并告诉它们最大增量是多少。

输入输出格式

输入格式:

第 1 行:两个整数 N, M。

第 2 到 M+1 行:第 i+1 行包含三个整数 A_i, B_i, L_i,A_i 和 B_i 表示道路 i 连接的田的编号,L_i 表示路长。

输出格式:

第 1 行:一个整数,表示通过使某条路加倍而得到的最大增量。

输入输出样例

输入样例#1: 复制

5 7
2 1 5
1 3 1
3 2 8
3 5 7
3 4 3
2 4 7
4 5 2

输出样例#1: 复制

2

说明

【样例说明】

若使 3 和 4 之间的道路长加倍,最短路将由 1-3-4-5 变为 1-3-5。

【数据规模和约定】

对于 30%的数据,N <= 70,M <= 1,500。

对于 100%的数据,1 <= N <= 100,1 <= M <= 5,000,1 <= L_i <= 1,000,000。

解题思路:

       这题我们可以发现n的范围只有100,m的范围是5000,所以我们可以先求一遍最短路,记下最短路的值和路径,枚举最短路上的每一条边,将这条边乘2再求一遍最短路,然后还原,最后输出最大的差值就行。

代码:

#include <iostream>
#include <cstring>
#include <string>
#include <algorithm>
#include <cmath>
#include <queue>
#define inf 0x3f3f3f3f
using namespace std;
int len[105][105];
int dis[105];
bool vis[105];int pre[105];
int main()
{
	int n,m;
	cin>>n>>m;
	for(int i=1;i<=m;i++)
	{
		int a,b,c;
		cin>>a>>b>>c;
		len[a][b]=c;
		len[b][a]=c;
	}
	memset(dis,inf,sizeof(dis));
	queue<int>q;
	q.push(1);
	vis[1]=1;
	dis[1]=0;
	while(!q.empty())
	{
		int now=q.front();
		q.pop();
		vis[now]=0;
		for(int i=1;i<=n;i++)
		{
			if(len[now][i]){
				if(dis[i]>dis[now]+len[now][i]){
					dis[i]=dis[now]+len[now][i];
					pre[i]=now;
					if(!vis[i]){
						q.push(i);
						vis[i]=1;
					}
				}
			}
		}
	}
	int tt=n;
	int sum=dis[n];tt=n;int r,l=n,Max=0;
	while(tt){
		r=l;
		l=pre[tt];
		tt=pre[tt];
		if(!tt)break;
		len[l][r]*=2;
		len[r][l]*=2;
		memset(vis,0,sizeof(vis));
		memset(dis,inf,sizeof(dis));
		q.push(1);
		vis[1]=1;
		dis[1]=0;
		while(!q.empty())
		{
			int now=q.front();
			q.pop();
			vis[now]=0;
			for(int i=1;i<=n;i++)
			{
				if(len[now][i]){
					if(dis[i]>dis[now]+len[now][i]){
						dis[i]=dis[now]+len[now][i];
						pre[i]=now;
						if(!vis[i]){
							q.push(i);
							vis[i]=1;
						}
					}
				}
			}
		}
		if(dis[n]>Max){
			Max=dis[n];
		}
		len[l][r]/=2;
		len[r][l]/=2;
		
	}
	cout<<Max-sum<<endl;
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_40400202/article/details/81068691