• [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 }
  • 相关阅读:
    0909 初识编译原理
    校园跳蚤市场-Sprint计划
    校园跳蚤市场
    5.2-5.3
    5.1封装
    阅读2
    汉堡包
    五章-问题
    结对子作业 四则运算 V2.0
    四则运算升级版
  • 原文地址:https://www.cnblogs.com/cervusy/p/9826949.html
Copyright © 2020-2023  润新知