太弱了。。。

一开始看到题感觉是跑一个最小生成树在上边进行LCA就行了,但是发现过不了样例,然后就是就想到了之前做过类似做法的题目,就是非生成树上的边最多只有21条,然后就那些边记录下来,通过每一条边的两个点跑lca然后取最小值

 ll ans=lca(x,y);for(int i=1;i<=k;i++)           {ans=min(ans,b[i].val+lca(x,b[i].x)+lca(y,b[i].y));ans=min(ans,b[i].val+lca(x,b[i].y)+lca(y,b[i].x));}cout<<ans<<endl;

这样发现也不行,想明白了之后你要求的可能是某两个点由多条非生成树边连接并且最短,emmm然后就没办法做了,没有想到转化成为这些非生成树边的点(最多42个)每一个点到两个询问点的距离,其实也就是跑40多次的最短路,用dij就可以卡过去。

我的做法就是先用kuske建立一个生成树(好像没有必要用kuske提出来最短边),跑dfs用倍增提前记录好父亲节点以备跑lca,然后记录其他没有在生成树里的边上的点,然后从这些点出发跑最短路,以Dis[i][x]记录第i个点到x的最短距离,然后询问x,y的最短路,就是将lca(x,y)与每一个Dis[i][x]+Dis[i][y]进行比较取最小值,即可得出答案。

代码如下

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<math.h>
#include<set>
#include<stack>
#include<vector>
#include<map>
#include<queue>
#define myself i,l,r
#define lson i<<1
#define rson i<<1|1
#define Lson i<<1,l,mid
#define Rson i<<1|1,mid+1,r
#define half (l+r)/2
#define inff 0x3f3f3f3f
#define lowbit(x) x&(-x)
#define PI 3.14159265358979323846
#define me(a,b) memset(a,b,sizeof(a))
#define min4(a,b,c,d) min(min(a,b),min(c,d))
#define min3(x,y,z) min(min(x,y),min(y,z))
#define pii make_pair
#define pli pair<long long,int >
const int dir[4][2]= {0,-1,-1,0,0,1,1,0};
typedef long long ll;
const ll inFF=9223372036854775807;
typedef unsigned long long ull;
using namespace std;
const int maxn=2e5+5;
int f[maxn][30],d[maxn],head[maxn];
int fa[maxn];
ll dis[maxn],Dis[50][maxn];
int vis[maxn],mm[50];
int sign,n,m,q,cnt;
map<ll,int>mp;
struct node
{int to,p;ll val;
}edge[maxn<<1];
struct nod
{int x,y;ll val;
}a[maxn];
struct eg {ll val;int next;bool friend operator<(eg q,eg e){return q.val>e.val;}
};
vector<eg>v[maxn];
bool cmp(nod s,nod e)
{return s.val<e.val;
}
void add(int u,int v,ll val)
{edge[sign]=node{v,head[u],val};head[u]=sign++;
}
int find(int x)
{if(x==fa[x]) return x;else return fa[x]=find(fa[x]);
}
void init()
{sign=cnt=0;mp.clear();for(int i=0;i<=n;i++){fa[i]=i;head[i]=-1;v[i].clear();}
}
void kuske()
{for(int i=1;i<=m;i++){int fx=find(a[i].x);int fy=find(a[i].y);int x=a[i].x,y=a[i].y;ll val=a[i].val;if(fx!=fy){fa[fx]=fy;add(a[i].x,a[i].y,a[i].val);//这是取出生成树的边跑倍增,其实可以直接dfs跑出来add(a[i].y,a[i].x,a[i].val);} else{if(mp[x]==0) mp[x]=++cnt,mm[cnt]=x;//记录那些点的顺序if(mp[y]==0) mp[y]=++cnt,mm[cnt]=y;}v[x].push_back(eg{val,y});//所有的边都加到里边跑dijv[y].push_back(eg{val,x});}
}
void dij(int id,int s)//跑出来Dis[i][x]第i点到每个点的最小距离
{for(int i=0;i<maxn;i++){vis[i]=0;Dis[id][i]=inFF;}Dis[id][s]=0;priority_queue<eg >q;q.push(eg{0,s});while(!q.empty()){eg now=q.top();q.pop();int u=now.next;if(now.val>Dis[id][u]) continue;vis[u]=1;//cout<<mm[id]<<"->"<<now.next<<" "<<Dis[id][u]<<endl;for(int i=0;i<v[u].size();i++){int next=v[u][i].next;ll val=v[u][i].val;if(vis[next]) continue;if(Dis[id][next]>Dis[id][u]+val){Dis[id][next]=Dis[id][u]+val;q.push(eg{Dis[id][next],next});}}}
}
void dfs(int u)
{for(int i=1;(1<<i)<=n;i++)f[u][i]=f[f[u][i-1]][i-1];for(int i=head[u];~i;i=edge[i].p){int v=edge[i].to;if(v==f[u][0]) continue;d[v]=d[u]+1;f[v][0]=u;dis[v]=dis[u]+edge[i].val;dfs(v);}
}
ll lca(int a,int b)//lca模板
{int s=a,e=b;if(d[a]<d[b]) swap(a,b);int x=d[a]-d[b];for(int i=0;(1<<i)<=x;i++)if((1<<i)&x) a=f[a][i];if(a!=b){for(int i=(int)log2(n);i>=0;i--)if(f[a][i]!=f[b][i]) a=f[a][i],b=f[b][i];a=f[a][0];}ll ans=dis[s]+dis[e]-2*dis[a];return ans;
}
int main()
{int x,y;while(cin>>n>>m){init();for(int i=1;i<=m;i++)scanf("%d %d %lld",&a[i].x,&a[i].y,&a[i].val);sort(a+1,a+1+m,cmp);kuske();for(int i=1;i<=cnt;i++)dij(i,mm[i]);f[1][0]=1,d[1]=0,dis[1]=0;dfs(1);cin>>q;while(q--){scanf("%d %d",&x,&y);ll ans=lca(x,y);for(int i=1;i<=cnt;i++)ans=min(ans,Dis[i][x]+Dis[i][y]);printf("%lld\n",ans);}}return 0;
}

The Shortest Statement CodeForces - 1051F LCA+最短路相关推荐

  1. 【Codeforces】1051F. The Shortest Statement【MST+LCA+最短路】

    F. The Shortest Statement [题目描述] 传送门 [题解] 题目也说了,重点是m-n<=20,我们就可以先跑最小生成树,最后剩下最多21条边,对着44个端点(包括起点和终 ...

  2. Educational Codeforces Round 51: F. The Shortest Statement(最短路+LCA)

    F. The Shortest Statement 题意: n个点m条边(m≤n+20)的无向连通图,Q次询问,每次求出给定两点的最短路 思路: 将题意转换一下,给你一棵n个节点的树,并且这个树上还有 ...

  3. Codeforces.1051F.The Shortest Statement(最短路Dijkstra)

    题目链接 先随便建一棵树. 如果两个点(u,v)不经过非树边,它们的dis可以直接算. 如果两个点经过非树边呢?即它们一定要经过该边的两个端点,可以直接用这两个点到 u,v 的最短路更新答案. 所以枚 ...

  4. 图论 ---- F. The Shortest Statement (最短路的性质 + 任意两点间最短路 + 图转树)

    题目链接 题目大意: 给你一个nnn个点mmm条边的无向图,就是动态询问任意两点间的最短路 n,m∈[1,1e5],m−n≤20n,m\in[1,1e5],m-n\leq20n,m∈[1,1e5],m ...

  5. cf1051F. The Shortest Statement(最短路)

    题意 题目链接 题意:给出一张无向图,每次询问两点之间的最短路,满足$m - n <= 20$ $n, m, q \leqslant 10^5$ Sol 非常好的一道题. 首先建出一个dfs树. ...

  6. A and B and Lecture Rooms CodeForces - 519E LCA+dfs序

    看到这个题的第一个思路就是就是统计以每一个点为根的所有节点个数,然后具体就分情况讨论一下即可. 因为刚刚学习了dfs序,这个题就用了dfs序来通过进出时间戳来相减表示其为根的子节点个数. 分情况 我们 ...

  7. HDU - 4725 The Shortest Path in Nya Graph(最短路+思维)

    题目链接:点击查看 题目大意:给定n个点,在一般的基础上给每个点一个维度,也就是多了一个参数表示所在的层次,现在已知: X层的点可以通过增加权值C到达X-1层或X+1层中的任何一个点 给定m个已经形成 ...

  8. Codeforces 360E 贪心 最短路

    题意及思路:https://blog.csdn.net/huanghongxun/article/details/49846927 在假设所有边都是最大值的情况下,如果第一个人能比第二个人先到,那就缩 ...

  9. Berland and the Shortest Paths CodeForces - 1005F(最短路树)

    最短路树就是用bfs走一遍就可以了 d[v] = d[u] + 1 表示v是u的前驱边 然后遍历每个结点 存下它的前驱边 再用dfs遍历每个结点 依次取每个结点的某个前驱边即可 #include &l ...

最新文章

  1. 页面A使用window.open打开页面B,然后取得B的返回值
  2. 通过一个函数对比 mgrid以及meshgrid函数
  3. UML从需求到实现---类图(2)
  4. Linux 3.0发布
  5. 跟踪Makefile输出调试信息
  6. 应届生,你凭什么认为你当得了产品经理?| PMCAFF
  7. 金泰联限量稳定虚拟主机赞助计划
  8. java面板如何设置大小_java面板调整大小问题
  9. html5跨域 postmessage,html5跨域通讯之postMessage的用法总结
  10. CentOs7安装JDK/Tomcat/Git/Gradle
  11. 《以截屏为基础的演示文档制作软件》(ScreenSteps Pro)更新v2.9.1/含注册机[压缩包]...
  12. mybatis加载xml配置文件
  13. 《Android游戏开发详解》一2.17 对象是独立的
  14. MySQL数据库几种常用的索引类型使用介绍
  15. varchar和varchar2之间的区别
  16. bugku(Crypto)---ook
  17. java算法编程题:某年某月某日是这一年的第几天
  18. 基于Vue的数据埋点统计
  19. 数据分析之信用风险评分卡建立
  20. 【狂飙后遗症】你磕的CP是那一对,他们的后代长什么样?

热门文章

  1. startActivity(xx,xx.class) 传递数据
  2. Android Studio添加代码头注释使用
  3. JLOI2011 飞行路线
  4. ARM Linux 基于S3C2451的AD9833波形发生器/Linux字符驱动的理解
  5. 2022-2028年中国反射偏光膜行业市场研究及前瞻分析报告
  6. 算法复习——bitset(bzoj3687简单题)
  7. OC实用转换model的工具
  8. asp.net断点续传技术
  9. 超市购物打印小票的简单程序 记录下来
  10. linux shell cgi post,linux下shell处理cgi的方法--post get