码迷,mamicode.com
首页 > 其他好文 > 详细

CF1433G Solution

时间:2021-03-08 13:21:10      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:make   solution   lan   inline   两种   ++   namespace   sizeof   lin   

题目链接

题解

下文将点\(x,y\)间的最短路长度称为\(<x,y>\)

若将边\(i\)的权值赋为\(0\),对于每组\(a_j,b_j\)有两种情况:最短路经过/不经过\(i\)。经过的情况花费\(=<a_j,u_i>+<b_j,v_i>\)\(<a_j,v_i>+<b_j,u_i>\),不经过的情况预处理出未更改边权的\(<a_j,b_j>\)即可。

AC代码

#include<bits/stdc++.h>
using namespace std;
const int N=1010,inf=0x3f3f3f3f;
int fst[N],nxt[2*N],u[2*N],v[2*N],w[2*N],cnt=1;
int a[N],b[N],dis[N],d[N],da[N];//d[i]:更改前的<a[i],b[i]>,da[i]:更改后的<a[i],u[i]>
bool vis[N];
priority_queue<pair<int,int> > q;
void add(int x,int y,int z)
{
	u[++cnt]=x,v[cnt]=y,w[cnt]=z;
	nxt[cnt]=fst[x],fst[x]=cnt;
}
void dij(int s)
{
	memset(dis,0x3f,sizeof(dis));
	memset(vis,0,sizeof(vis));
	q.push(make_pair(0,s)); dis[s]=0;
	while(!q.empty())
	{
		int x=q.top().second; q.pop();
		if(vis[x]) continue;
		vis[x]=1;
		for(int i=fst[x];i;i=nxt[i])
		{
			int y=v[i];
			if(dis[y]>dis[x]+w[i])
			{
				dis[y]=dis[x]+w[i];
				q.push(make_pair(-dis[y],y));
			}
		}
	}
}
int main()
{
	int n,m,k,ans=inf;
	scanf("%d%d%d",&n,&m,&k);
	int x,y,z;
	for(int i=1;i<=m;i++)
	{
		scanf("%d%d%d",&x,&y,&z);
		add(x,y,z),add(y,x,z);
	}
	for(int i=1;i<=k;i++) 
	{
		scanf("%d%d",&a[i],&b[i]);
		dij(a[i]); d[i]=dis[b[i]];
	}
	for(int i=2;i<=2*m+1;i++)//因为每条双向边正反存了2次,不用分类讨论
	{
		int sum=0,t=w[i]; w[i]=w[i^1]=0;//sum:将边i权值赋为0的总花费
		dij(u[i]);
		for(int j=1;j<=k;j++) da[j]=dis[a[j]];
		dij(v[i]);
		for(int j=1;j<=k;j++) sum+=min(da[j]+dis[b[j]],d[j]);
		ans=min(ans,sum); w[i]=w[i^1]=t;
	}
	printf("%d",ans);	
	return 0;
}

CF1433G Solution

标签:make   solution   lan   inline   两种   ++   namespace   sizeof   lin   

原文地址:https://www.cnblogs.com/violetholmes/p/14492318.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!