杭电第三场 Tokitsukaze and Rescue 图

Tokitsukaze and Rescue

题目链接

题目大意

给一张完全图,每个边有边权。
问删掉k条边让从1到n的最短路最长,问这个最长的距离是多少?
边权随机,点的个数: 50

题解

做的时候,感觉到了这个题很暴力,但是没想到这么暴力。。
做的题少,主要不知道边权随机是干嘛用的。。
就是爆搜。。
跑一个最短路,枚举最短路上的边,然后删掉,继续跑最短路,继续枚举。
这样的话,复杂度是在这里插入图片描述
这。。谁敢写啊。。
但是题解说由于边权随机,所以最短路径上的边的数量不是很多,这样可以过。。

#include <algorithm>
#include <cstdio>
#include <iostream>
#include <vector>
#include <stack>
#include <queue>
#include <map>
// #include <unordered_map>
#include <cmath>
#include <set>
#include <cstring>
#include <string>
// #include <unordered_set>
#include <bitset>
#include <stdlib.h>
#include <time.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
typedef unsigned long long ull;
typedef set<int>::iterator sit;
#define st first
#define sd second
#define mkp make_pair
#define pb push_back
void wenjian(){freopen("concatenation.in","r",stdin);freopen("concatenation.out","w",stdout);}
void tempwj(){freopen("hash.in","r",stdin);freopen("hash.out","w",stdout);}
ll gcd(ll a,ll b){return b == 0 ? a : gcd(b,a % b);}
ll qpow(ll a,ll b,ll mod){a %= mod;ll ans = 1;while(b){if(b & 1)ans = ans * a % mod;a = a * a % mod;b >>= 1;}return ans;}
struct cmp{bool operator()(const pii & a, const pii & b){return a.second < b.second;}};
int lb(int x){return  x & -x;}
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll mod = 1e9 + 7;
const int maxn = 55+10;
int dis[maxn][maxn];
int per[maxn][maxn];
int vis[maxn];
int d[maxn];
int n;
void dj(int f)
{
	for(int i = 1; i <= n; i ++ )
	{
		vis[i] = 0;
		d[i] = dis[1][i];
		per[f][i] = 1;
	}
	for (int  i=  1; i < n; i ++ )
	{
		int minn = inf, k = -1;
		for (int j = 1; j <= n; j ++ )
		{
			if(vis[j] == 0 && minn > d[j])
			{
				minn = d[j];
				k = j;
			}
		}
		if(k == -1)
			break;
		vis[k] = 1;
		for(int j = 1; j <= n; j ++ )
		{
			if(vis[j] == 0 && d[j] > d[k] + dis[k][j])
			{
				d[j] = d[k] + dis[k][j];
				per[f][j] = k;
			}
		}
	}
}
int ans = 0;
void dfs(int num)
{
	// printf("%d\n",num);
	dj(num);
	if(num == 0)
	{
		ans = max(ans,d[n]);
		return;
	}
	// for(int i = 1; i <= n; i ++ )
	// {
	// 	int k = dis[per[num][i]][i];
	// 	dis[per[num][i]][i] = inf;
	// 	dis[i][per[num][i]] = inf;
	// 	dfs(num - 1);
	// 	dis[per[num][i]][i] = dis[i][per[num][i]] = k;
	// }
	int temp;
	for(int i = n; i != 1; i = temp)
	{
		temp = per[num][i];
		// printf("%d\n", temp);
		int k = dis[temp][i];
		dis[temp][i] = dis[i][temp] = inf;
		dfs(num - 1);
		dis[temp][i] = dis[i][temp] = k;
	}
}


int main()
{
	int T;
	scanf("%d",&T);
	while(T -- )
	{
		ans =0 ;
		int m;
		scanf("%d%d",&n,&m);
		for(int i=1; i<=n; i++)for(int j=1; j<=n; j++)dis[i][j]=i==j?0:inf;
		for (int  i= 1; i<= n * (n - 1) / 2; i ++ )
		{
			int x,y,v;
			scanf("%d%d%d",&x,&y,&v);
			dis[x][y] = dis[y][x] = v;
		}
		dfs(m);
		cout<<ans<<endl;
	}
}

这道题。。。 做的时候想了很多,,什么分层图,网络流,二分之类的都想了,但是感觉都不是,于是就没完了。。。没想到这么暴力,一定要会算时间复杂度。好重要呀。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值