zoukankan      html  css  js  c++  java
  • [CF1051F] The Shortest Statement

    CF 题目传送门

    洛谷 题目传送门

    一道最短路的题。

    首先题目条件给出m-n<=20,可以看出这个图近乎一棵树。

    首先跑出图的dfs树,预处理出树上距离等信息。

    再枚举非树边,对每一个非树边的端点跑一边dijkstra。

    可以看出最多有42个这样的点。

    回答询问的时候,用树上距离作为答案,再用每一个非树边的端点更新答案即可。

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 #include<queue>
      5 #define ll long long
      6 #define bro(i) ((i%2)?(i+1):(i-1))
      7 #define MAXN 100005
      8 using namespace std;
      9 
     10 int n,m,q;
     11 int hd[MAXN],to[MAXN<<1],nx[MAXN<<1],fr[MAXN<<1],ec;
     12 bool used[MAXN<<1];
     13 ll len[MAXN<<1];
     14 
     15 void edge(int af,int at,ll el)
     16 {
     17     to[++ec]=at;
     18     fr[ec]=af;
     19     nx[ec]=hd[af];
     20     len[ec]=el;
     21     hd[af]=ec;
     22 }
     23 
     24 int f[MAXN][20],dep[MAXN];
     25 
     26 namespace treedata
     27 {
     28     ll dis[MAXN];
     29 }
     30 
     31 namespace graphdata
     32 {
     33     ll dis[50][MAXN];
     34 }
     35 
     36 void dfs(int p,int fa,ll dl)
     37 {
     38     using namespace treedata;
     39     f[p][0]=fa;
     40     dep[p]=dep[fa]+1;
     41     dis[p]=dis[fa]+dl;
     42     for(int i=hd[p];i;i=nx[i])
     43         if(!dep[to[i]])
     44             dfs(to[i],p,len[i]),used[i]=used[bro(i)]=1;
     45 }
     46 
     47 void pre()
     48 {
     49     for(int i=1;i<=18;i++)
     50         for(int j=1;j<=n;j++)
     51             f[j][i]=f[f[j][i-1]][i-1];
     52 }
     53 
     54 int lca(int x,int y)
     55 {
     56     if(dep[x]<dep[y])swap(x,y);
     57     for(int i=18;i>=0;i--)
     58         if(dep[f[x][i]]>=dep[y])x=f[x][i];
     59     if(x==y)return x;
     60     for(int i=18;i>=0;i--)
     61         if(f[x][i]!=f[y][i])x=f[x][i],y=f[y][i];
     62     return f[x][0];
     63 }
     64 
     65 bool mark[MAXN];
     66 int id[MAXN],mc;
     67 bool v[MAXN];
     68 
     69 struct data
     70 {
     71     int p;
     72     ll d;
     73     friend bool operator < (data q,data w)
     74     {
     75         return q.d>w.d;
     76     }
     77 };
     78 
     79 priority_queue<data>qq;
     80 
     81 void dijkstra(int s)
     82 {
     83     while(!qq.empty())qq.pop();
     84     using namespace graphdata;
     85     memset(v,0,sizeof(v));
     86     memset(dis[id[s]],0x3f,sizeof(dis[id[s]]));
     87     dis[id[s]][s]=0;
     88     qq.push((data){s,0});
     89     while(!qq.empty())
     90     {
     91         data nw=qq.top();
     92         qq.pop();
     93         if(v[nw.p])continue;
     94         v[nw.p]=1;
     95         for(int i=hd[nw.p];i;i=nx[i])
     96         {
     97             if((!v[to[i]])&&dis[id[s]][to[i]]>nw.d+len[i])
     98             {
     99                 dis[id[s]][to[i]]=nw.d+len[i];
    100                 qq.push((data){to[i],dis[id[s]][to[i]]});
    101             }
    102         }
    103     }
    104 }
    105 
    106 ll treedis(int x,int y)
    107 {
    108     using namespace treedata;
    109     int l=lca(x,y);
    110     return dis[x]+dis[y]-(dis[l]<<1);
    111 }
    112 
    113 ll graphdis(int x,int y,int sid)
    114 {
    115     using namespace graphdata;
    116     return dis[sid][x]+dis[sid][y];
    117 }
    118 
    119 int main()
    120 {
    121     scanf("%d%d",&n,&m);
    122     for(int i=1;i<=m;i++)
    123     {
    124         int a,b;ll c;
    125         scanf("%d%d%I64d",&a,&b,&c);
    126         edge(a,b,c);
    127         edge(b,a,c);
    128     }
    129     dfs(1,1,0);
    130     pre();
    131     for(int i=1;i<=ec;i+=2)
    132         if(!used[i])
    133             mark[fr[i]]=mark[to[i]]=1;
    134     for(int i=1;i<=n;i++)
    135     {
    136         if(!mark[i])continue;
    137         id[i]=++mc;
    138         dijkstra(i);
    139     }
    140     scanf("%d",&q);
    141     for(int i=1;i<=q;i++)
    142     {
    143         int x,y;
    144         scanf("%d%d",&x,&y);
    145         ll ans=treedis(x,y);
    146         for(int j=1;j<=mc;j++)
    147             ans=min(ans,graphdis(x,y,j));
    148         printf("%I64d
    ",ans);
    149     }
    150     return 0;
    151 }
  • 相关阅读:
    康复计划
    Leetcode 08.02 迷路的机器人 缓存加回溯
    Leetcode 38 外观数列
    Leetcode 801 使序列递增的最小交换次数
    Leetcode 1143 最长公共子序列
    Leetcode 11 盛水最多的容器 贪心算法
    Leetcode 1186 删除一次得到子数组最大和
    Leetcode 300 最长上升子序列
    Leetcode95 不同的二叉搜索树II 精致的分治
    Leetcode 1367 二叉树中的列表 DFS
  • 原文地址:https://www.cnblogs.com/eternhope/p/9826949.html
Copyright © 2011-2022 走看看