zoukankan      html  css  js  c++  java
  • CF1051F The Shortest Statement (最短路)

    题目大意:一个无向连通图,n个点m条边,n<=1e5,m-n<=20,q个询问,q<=1e5,求u和v之间的最短路

    发现边只比点多20个,所以可以把图当成一棵树,求出图的最小生成树

    对于一个询问,最短路径可能是两个点的树上最小距离,但最短路径也有可能经过未被加入最小生成树的边

    那怎么办呢?

    发现m-n<=20,预处理出未被加入最小生成树的边,相连的其中一个节点,去跑spfa(因为是稀疏图不怕被卡),一共跑21次spfa即可

    如果最短路径经过未被加入最小生成树的边,那么一定经过这条边相连的两个节点

    每个询问的答案就是最小生成树上两点的距离 或者是 这21次spfa中两点之间的距离即可

    时间$O(20(n+e+q))$,稀疏图spfa时间近似等于$(O(n+e))$

      1 #include <queue>
      2 #include <cstdio>
      3 #include <algorithm>
      4 #include <cstring>
      5 #define ll long long
      6 #define N 100010
      7 #define uint unsigned int
      8 #define inf 0x3f3f3f3f3f3f3fll
      9 using namespace std;
     10 //re
     11 int gint()
     12 {
     13     int ret=0,fh=1;char c=getchar();
     14     while(c<'0'||c>'9'){if(c=='-')fh=-1;c=getchar();}
     15     while(c>='0'&&c<='9'){ret=(ret<<3)+(ret<<1)+c-'0';c=getchar();}
     16     return ret*fh;
     17 }
     18 
     19 int n,m,cte,num;
     20 int head[N],fa[N];
     21 struct Edge{int to,nxt;ll val;}edge[N*2];
     22 
     23 int find_fa(int x){
     24     int y=x,pre;while(y!=fa[y])y=fa[y];
     25     while(fa[x]!=y){pre=fa[x],fa[x]=y,x=pre;}
     26     return y;
     27 }
     28 void ae(int u,int v,int w){
     29     cte++;edge[cte].to=v,edge[cte].val=w;
     30     edge[cte].nxt=head[u],head[u]=cte;
     31 }
     32 
     33 struct Krus{int x,y,flag;ll val;}e[N];
     34 int cmp(Krus s1,Krus s2){return s1.val<s2.val;}
     35 void Kruskal()
     36 {
     37     int x,y,fx,fy;
     38     for(int i=1;i<=n;i++) fa[i]=i;
     39     sort(e+1,e+m+1,cmp);
     40     for(int i=1;i<=m;i++){
     41         x=e[i].x,y=e[i].y,fx=find_fa(x),fy=find_fa(y);
     42         if(fx!=fy) e[i].flag=1,fa[fy]=fx,ae(x,y,e[i].val),ae(y,x,e[i].val);
     43     }memset(fa,0,sizeof(fa));
     44 }
     45 
     46 int use[N];
     47 struct SBFA{
     48     ll dis[N];int S;
     49     void Main(int s)
     50     {
     51         memset(dis,0x3f,sizeof(dis));
     52         S=s;queue<int>q;q.push(S);
     53         dis[S]=0,use[S]=1;
     54         while(!q.empty()){
     55             int u=q.front();q.pop();
     56             for(int j=head[u];j;j=edge[j].nxt){
     57                 int v=edge[j].to;
     58                 if(dis[v]>dis[u]+edge[j].val){
     59                     dis[v]=dis[u]+edge[j].val;
     60                     if(!use[v]) q.push(v),use[v]=1;
     61                 }
     62             }use[u]=0;
     63         }
     64     }
     65 }sbfa[22];
     66 
     67 ll dis[N];int dep[N],sz[N],son[N],tp[N];
     68 void dfs1(int u,int dad)
     69 {
     70     for(int j=head[u];j;j=edge[j].nxt){
     71         int v=edge[j].to;
     72         if(v==dad) continue;
     73         fa[v]=u,dep[v]=dep[u]+1;
     74         dis[v]=dis[u]+edge[j].val;
     75         dfs1(v,u);sz[u]+=sz[v];
     76         son[u]=sz[v]>sz[son[u]]?v:son[u];
     77     }sz[u]++;
     78 }
     79 void dfs2(int u){
     80     if(son[u]) tp[son[u]]=tp[u],dfs2(son[u]);
     81     for(int j=head[u];j;j=edge[j].nxt){
     82         int v=edge[j].to;
     83         if(v==fa[u]||v==son[u]) continue;
     84         tp[v]=v;dfs2(v);
     85     }
     86 }
     87 int Lca(int x,int y){
     88     while(tp[x]!=tp[y]){
     89         if(dep[tp[x]]<dep[tp[y]]) swap(x,y);
     90         x=fa[tp[x]];
     91     }return dep[x]<dep[y]?x:y;
     92 }
     93 
     94 ll solve(int x,int y){
     95     int lca=Lca(x,y);
     96     ll ans=dis[x]+dis[y]-dis[lca]*2;
     97     for(int i=0;i<num;i++)
     98         ans=min(ans,sbfa[i].dis[x]+sbfa[i].dis[y]);
     99     return ans;
    100 }
    101 
    102 int main()
    103 {
    104     scanf("%d%d",&n,&m);
    105     int x,y;
    106     for(int i=1;i<=m;i++)
    107         e[i].x=gint(),e[i].y=gint(),e[i].val=gint();
    108     Kruskal();
    109     dep[1]=1,dfs1(1,-1);
    110     tp[1]=1,dfs2(1);
    111     for(int i=1;i<=m;i++)
    112         if(!e[i].flag){ae(e[i].x,e[i].y,e[i].val),ae(e[i].y,e[i].x,e[i].val);}
    113     for(int i=1;i<=m;i++)
    114         if(!e[i].flag){sbfa[num].Main(e[i].x),num++;}
    115     int q;scanf("%d",&q);
    116     for(int i=1;i<=q;i++){
    117         x=gint(),y=gint();
    118         printf("%I64d
    ",solve(x,y));
    119     }
    120     return 0;
    121 }
  • 相关阅读:
    LeetCode——Generate Parentheses
    LeetCode——Best Time to Buy and Sell Stock IV
    LeetCode——Best Time to Buy and Sell Stock III
    LeetCode——Best Time to Buy and Sell Stock
    LeetCode——Find Minimum in Rotated Sorted Array
    Mahout实现基于用户的协同过滤算法
    使用Java对文件进行解压缩
    LeetCode——Convert Sorted Array to Binary Search Tree
    LeetCode——Missing Number
    LeetCode——Integer to Roman
  • 原文地址:https://www.cnblogs.com/guapisolo/p/9811763.html
Copyright © 2011-2022 走看看