【最短路Dijkstra】CC_CLIQUED Bear and Clique Distances

【题目】
CC
一幅 n n n个点的图,其中前 k k k个点之间两两有一条长度为 x x x的无向边。除此之外还有 m m m条长度为 w i w_i wi的无向边。
S S S到所有点的最短路。
n , k ≤ 1 0 5 n,k\leq 10^5 n,k105

【解题思路】
不知道怎么就开始写起了水题。

完全图边比较多,我们缩一缩规模,只需要将前 k k k个点与一个新点 T T T连边 x 2 \frac x 2 2x,其他边照连即可。

复杂度 O ( ( n + k ) log ⁡ k ) O((n+k)\log k) O((n+k)logk),实现上可以将所有边权乘 2 2 2,最后除以 2 2 2,就可以避免实数了。

【参考代码】

#include
#define fi first
#define se second
#define mkp make_pair
using namespace std;

typedef long long ll;
typedef pair<ll,int> pii;
const int N=1e5+10;

int read()
{
	int ret=0;char c=getchar();
	while(!isdigit(c)) c=getchar();
	while(isdigit(c)) ret=ret*10+(c^48),c=getchar();
	return ret;
}
void write(ll x){if(x>9)write(x/10);putchar(x%10^48);}
void writesp(ll x){write(x);putchar(' ');}

namespace DreamLolita
{
	int n,K,X,m,S,tot;
	int head[N],vis[N];
	ll dis[N];
	priority_queue<pii,vector<pii>,greater<pii> >q;
	struct Tway{int v,w,nex;}e[N<<2];
	void add(int u,int v,int w)
	{
		e[++tot]=(Tway){v,w,head[u]};head[u]=tot;
		e[++tot]=(Tway){u,w,head[v]};head[v]=tot;
	}
	void dij()
	{
		dis[S]=0;q.push(mkp(dis[S],S));
		while(!q.empty())
		{
			int x=q.top().se;q.pop();
			if(vis[x])continue; vis[x]=1;
			for(int i=head[x];i;i=e[i].nex)
			{
				int v=e[i].v;
				if(!vis[v]) dis[v]=min(dis[v],dis[x]+e[i].w),q.push(mkp(dis[v],v));
			}
		}
	}
	void clear()
	{
		tot=0;
		memset(head,0,sizeof(head));memset(dis,0x3f,sizeof(dis));memset(vis,0,sizeof(vis));
	}
	void solution()
	{
		clear();
		n=read();K=read();X=read();m=read();S=read();
		for(int i=1,u,v;i<=m;++i) u=read(),v=read(),add(u,v,read()*2);
		for(int i=1;i<=K;++i) add(i,n+1,X); 
		dij();for(int i=1;i<=n;++i) writesp(dis[i]/2); puts("");
	}
}

int main()
{
#ifdef Durant_Lee
	freopen("CC_CLIQUED.in","r",stdin);
	freopen("CC_CLIQUED.out","w",stdout);
#endif
	int T=read();
	while(T--) DreamLolita::solution();
	return 0;
}

你可能感兴趣的:(图论-最短路)