这道题思路比较有意思,第一次做完全没想到点子上。。。


看到题目第一反应是一道最短路裸题,但是数据范围1e5说明完全不可能。

这个时候可以观察到题目给出了一个很有意思的条件,就是说边最多比点多20。

这有什么用呢?

那么我们大胆猜想,可否将整个图划分为21条边(连接最多42个点)和一颗树?(极限情况)

如果这样的话,对于任意的两个节点uv,它们之间的最短路只有两种情况:

  1. 这两个点都在树上。所以说最短路必然是u->lca(u,v)->v。

  2. 不是上面那种情况。这个时候肯定会有连到外面那21个边。我们暴力枚举一下就可以了。

到这里思路就完全出来了,我们先把不属于树的点挑出来,对每一个都跑一下最短路。

然后对于每一组询问判断一下属于哪一种情况就可以了。


AC代码如下:

37657ms 67712kb

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
namespace StandardIO{
template<typename T>inline void read(T &x){
x=0;T f=1;char c=getchar();
for(;c<'0'||c>'9';c=getchar())if(c=='-')f=-1;
for(;c>='0'&&c<='9';c=getchar())x=x*10+c-'0';
x*=f;
}
template<typename T>inline void write(T x){
if(x<0)putchar('-'),x*=-1;
if(x>=10)write(x/10);
putchar(x%10+'0');
}
}
using namespace StandardIO;
namespace Solve{
#define int long long
const int N=100100;
const int INF=2147483647;
int n,m,p;
int cnt;
int head[N];
struct node{
int to,val,next;
}edge[N<<1];
template<typename T>inline void add(T a,T b,T c){
edge[++cnt].to=b,edge[cnt].val=c,edge[cnt].next=head[a],head[a]=cnt;
}
struct qnode{
int key,val;
bool operator < (qnode x)const{
return val>x.val;
}
};
int top;
int vis[N],fa[N][23],dist[N],dep[N],q[N];
int dis[50][N];
inline void dfs(int now,int father){
vis[now]=1,fa[now][0]=father;
for(register int i=head[now];i;i=edge[i].next){
int to=edge[i].to;
if(to==father)continue;
if(vis[to])q[++top]=now,q[++top]=to;
else{
dep[to]=dep[now]+1,dist[to]=dist[now]+edge[i].val;
dfs(to,now);
}
}
}
template<typename T>inline T lca(T x,T y){
if(dep[x]<dep[y])swap(x,y);
for(register int i=19;i>=0;--i){
if(dep[fa[x][i]]>=dep[y])x=fa[x][i];
}
if(x==y)return x;
for(register int i=19;i>=0;--i){
if(fa[x][i]!=fa[y][i]){
x=fa[x][i],y=fa[y][i];
}
}
return fa[x][0];
}
inline void dijkstra(int now){
memset(dis[now],63,sizeof(dis[now]));
memset(vis,0,sizeof(vis));
priority_queue<qnode>Q;
dis[now][q[now]]=0;
Q.push((qnode){q[now],0});
while(!Q.empty()){
int tmp=Q.top().key;Q.pop();
if(vis[tmp])continue;
vis[tmp]=1;
for(register int i=head[tmp];i;i=edge[i].next){
int to=edge[i].to;
if(!vis[to]&&dis[now][tmp]+edge[i].val<dis[now][to]){
dis[now][to]=dis[now][tmp]+edge[i].val;
Q.push((qnode){to,dis[now][to]});
}
}
}
}
inline void solve(){
read(n),read(m);
for(register int i=1;i<=m;++i){
int a,b,c;
read(a),read(b),read(c);
add(a,b,c),add(b,a,c);
}
dep[1]=1,dfs(1,0);
for(register int j=1;j<=19;++j){
for(register int i=1;i<=n;++i){
fa[i][j]=fa[fa[i][j-1]][j-1];
}
}
sort(q+1,q+top+1);top=unique(q+1,q+top+1)-q-1;
for(register int i=1;i<=top;++i)dijkstra(i);
read(p);
while(p--){
int x,y;
read(x),read(y);
int ans=dist[x]+dist[y]-2*dist[lca(x,y)];
for(register int i=1;i<=top;++i)ans=min(ans,dis[i][x]+dis[i][y]);
write(ans),putchar('\n');
}
}
}
using namespace Solve;
#undef int
int main(){
solve();
}

最新文章

  1. Android 6.0 - 动态权限管理的解决方案
  2. MM常用BADI
  3. js替换选中的文字
  4. tar等
  5. [moka同学笔记]yii2.0表单的使用
  6. Oracle 行迁移和行链接
  7. JavaWeb笔记——利用过滤器实现页面静态化
  8. JavaScript创建Map对象(转)
  9. 【windows socket+TCPserverclient】
  10. MyDatePicker拆分日期显示到不同TextBox
  11. Python (九) 协程以及数据库操作
  12. smartClient 1--框架介绍
  13. aps .net MVC单用户登录
  14. 快速掌握Nginx(二) —— Nginx的Location和Rewrite
  15. Kafka详细配置
  16. #Java学习之路——基础阶段(第九篇)
  17. html/css/js----js中遇到的一些问题
  18. Shell data、timedatectl
  19. java虚拟机之虚拟机类加载机制
  20. 2018-2019-1 1723《程序设计与数据结构》第5&amp;6&amp;7周作业 总结

热门文章

  1. 【hihocoder 1303】模线性方程组
  2. CF789A. Anastasia and pebbles
  3. HDU 2857 Mirror and Light
  4. js 阻止冒泡
  5. yiii 数据库备份导出
  6. HDU 4342
  7. 鸟书shell 学习笔记(二) shell中正則表達式相关
  8. 一种基于Qt的可伸缩的全异步C/S架构server实现(五) 单层无中心集群
  9. Quartz2D二维画图引擎
  10. DOM基础----DOM(一)