习题:The Shortest Statement(dij&LCA)
题目
思路
注意到边的数量很特殊,只比点的数量多了20不到
先建一颗生成树,如果不用多的边,那每两个的之间的距离就可以直接LCA来求
考虑如果多的边有用,设这些多的边的端点的集合为P,那么一定是从起点到P中的某一个元素,再到P中的另一个元素,再到终点,所以对P中的每一个元素进行一次dij,
最后的答案跟LCA进行比较即可
代码
#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
using namespace std;
namespace IO
{
void read(int &x)
{
x=0;
int f=1;
char c=getchar();
while('0'>c||c>'9')
{
if(c=='-')
f=-1;
c=getchar();
}
while('0'<=c&&c<='9')
{
x=(x<<3)+(x<<1)+c-'0';
c=getchar();
}
x*=f;
}
void read(long long &x)
{
x=0;
int f=1;
char c=getchar();
while('0'>c||c>'9')
{
if(c=='-')
f=-1;
c=getchar();
}
while('0'<=c&&c<='9')
{
x=(x<<3)+(x<<1)+c-'0';
c=getchar();
}
x*=f;
}
void write(int x)
{
if(x<10)
putchar(x+'0');
else
{
write(x/10);
putchar(x%10+'0');
}
}
void write(long long x)
{
if(x<10)
putchar(x+'0');
else
{
write(x/10);
putchar(x%10+'0');
}
}
}
using namespace IO;
struct node
{
int e;
long long w;
friend bool operator < (const node &a,const node &b)
{
return a.w>b.w;
}
};
int n,m,Q;
int dp_ind[100005][25],dep[100005];
long long dp_w[100005][25],dis[45][100005];
bool used[100005],vis[100005];
vector<int> p;
vector<node> g[100005];
priority_queue<node> q;
void dfs(int u,int fa)
{
dep[u]=dep[fa]+1;
for(int i=1;i<=20;i++)
{
dp_ind[u][i]=dp_ind[dp_ind[u][i-1]][i-1];
dp_w[u][i]=dp_w[u][i-1]+dp_w[dp_ind[u][i-1]][i-1];
}
used[u]=1;
for(int i=0;i<g[u].size();i++)
{
int v=g[u][i].e;
if(v==fa)
continue;
else if(used[v])
{
if(vis[u]==0)
{
vis[u]=1;
p.push_back(u);
}
if(vis[v]==0)
{
vis[v]=1;
p.push_back(v);
}
}
else
{
dp_ind[v][0]=u;
dp_w[v][0]=g[u][i].w;
dfs(v,u);
}
}
}
long long lca(int u,int v)
{
long long w=0;
if(u==v)
return w;
if(dep[u]>dep[v])
swap(u,v);
for(int i=20;i>=0;i--)
if(dep[u]<=dep[dp_ind[v][i]])
{
w=w+dp_w[v][i];
v=dp_ind[v][i];
}
if(u==v)
return w;
for(int i=20;i>=0;i--)
{
if(dp_ind[u][i]!=dp_ind[v][i])
{
w=w+dp_w[u][i];
w=w+dp_w[v][i];
u=dp_ind[u][i];
v=dp_ind[v][i];
}
}
return w+dp_w[u][0]+dp_w[v][0];
}
void dij(int s,long long *dis)
{
q.push((node){s,0});
while(!q.empty())
{
node t=q.top();
q.pop();
if(t.w>dis[t.e])
continue;
dis[t.e]=t.w;
for(int i=0;i<g[t.e].size();i++)
{
int v=g[t.e][i].e;
if(t.w+g[t.e][i].w<dis[v])
q.push((node){v,t.w+g[t.e][i].w});
}
}
}
int main()
{
memset(dis,0x3f,sizeof(dis));
read(n);read(m);
for(int i=1,u,v;i<=m;i++)
{
long long w;
read(u);read(v);read(w);
g[u].push_back((node){v,w});
g[v].push_back((node){u,w});
}
dfs(1,0);
for(int i=0;i<p.size();i++)
dij(p[i],dis[i]);
read(Q);
for(int i=1,u,v;i<=Q;i++)
{
read(u);read(v);
long long ans=(1ll<<60);
for(int i=0;i<p.size();i++)
for(int j=0;j<p.size();j++)
ans=min(ans,dis[i][u]+dis[i][p[j]]+dis[j][v]);
write(min(ans,lca(u,v)));
putchar('\n');
}
return 0;
}

浙公网安备 33010602011771号