标签: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>\)即可。
#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;
}
标签:make solution lan inline 两种 ++ namespace sizeof lin
原文地址:https://www.cnblogs.com/violetholmes/p/14492318.html