Codeforces Round #575 (Div. 3) F. K-th Path

链接

https://codeforces.com/contest/1196/problem/F

题解

用到的肯定只有前 k k k大的边
所以只保留前 k k k大的边以及关联的点,最多 2 k 2k 2k个点
在这张图上用 d i j k s t r a dijkstra dijkstra求出两两点之间的最短路
时间复杂度 O ( k 2 l o g k ) O(k^2logk) O(k2logk)

代码

#include<bits/stdc++.h>
#define maxn 200010
#define maxe 400010
#define linf (1ll<<60)
#define iinf 0x3f3f3f3f
#define eps 1e-8
#define cl(x) memset(x,0,sizeof(x))
#define mod 1000000007ll
using namespace std;
typedef long long ll;
ll read(ll x=0)
{
	int c, f=1;
	for(c=getchar();!isdigit(c);c=getchar())if(c=='-')f=-f;
	for(;isdigit(c);c=getchar())x=x*10+c-48;
	return f*x;
}
ll n, dis[maxn];
struct Graph
{
    int etot, head[maxn], to[maxe], next[maxe], w[maxe];
    void clear(int N)
    {
        int i;
        for(i=1;i<=N;i++)head[i]=0;
        for(i=1;i<=etot;i++)to[i]=next[i]=w[i]=0;
        etot=0;
    }
    void adde(int a, int b, int c){to[++etot]=b;w[etot]=c;next[etot]=head[a];head[a]=etot;}
}G;
ll N, M, K;
struct Dijkatra
{
	ll dist[maxn];
	priority_queue<pair<ll,ll>> heap;
	typedef pair<ll,ll> pr;
	void clear(int N, ll opt=-1)	//opt=-1表示求最短路,opt=1表示求最长路
	{
		for(auto i=1;i<=N;i++)dist[i]=opt*linf;
	}
	void run(Graph& G, ll S, ll opt=-1)
	{
		heap.emplace(pr(dist[S]=0,S));
		while(!heap.empty())
		{
			pr x;
			do x=heap.top(), heap.pop();
			while(x.first!=dist[x.second] and !heap.empty());
			for(auto p=G.head[x.second];p;p=G.next[p])
			{
				if(dist[G.to[p]]<dist[x.second]+opt*G.w[p])
				{
					dist[G.to[p]]=dist[x.second]+opt*G.w[p];
					heap.emplace(pr(dist[G.to[p]],G.to[p]));
				}
			}
		}
	}
}dij;
struct edge
{
	ll u, v, w;
}e[maxn];
int main()
{
	ll i, j, k;
	N=read(), M=read(), K=read();
	for(i=1;i<=M;i++)e[i].u=read(), e[i].v=read(), e[i].w=read();
	sort(e+1,e+M+1,[](edge e1, edge e2){return e1.w<e2.w;});
	set<ll> st;
	for(i=1;i<=K and i<=M;i++)
	{
		st.emplace(e[i].u);
		st.emplace(e[i].v);
	}
	map<ll,ll> tb;
	ll tot=0;
	for(auto x:st)tb[x]=++tot;
	G.clear(tot);
	for(i=1;i<=K and i<=M;i++)
	{
		if(st.count(e[i].u) and st.count(e[i].v))
		{
			G.adde(tb[e[i].u],tb[e[i].v],e[i].w);
			G.adde(tb[e[i].v],tb[e[i].u],e[i].w);
		}
	}
	vector<ll> lis;
	for(i=1;i<=tot;i++)
	{
		dij.clear(tot);
		dij.run(G,i);
		for(j=i;j<=tot;j++)if(i<j)lis.emplace_back(dij.dist[j]);
	}
	for(auto &x:lis)x=-x;
	sort(lis.begin(),lis.end());
	cout<<lis.at(K-1);
	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值