zoukankan      html  css  js  c++  java
  • ACM-ICPC 2018 徐州赛区网络预赛 J. Maze Designer <<LCA+tarjin离线+最小生成树(邻接表储存)

    题意

    在一个n*m的地图的线上造迷宫,给出每条边的造价,造出迷宫,使得地图上任两点有且仅有一条路,使迷宫造价最低,题目保证这样的迷宫唯一。建出迷宫之后有q次询问,询问两点间的距离。

    思路

    迷宫构造问题,起初没有思路,在一段思索之后和鸡神想出了反其道而行之的办法,先假设所有墙都有,我们要满足题设条件就要砸墙,每次砸最贵的墙,构成一颗生成树,所以就是建造这个迷宫就是求一个最大生成树的问题了,在此选用了kruskal算法。

    而后把这棵树存下来,然后就是想办法求树上任两点距离就行了,方法很多,但我和鸡神一种都不会,所以赛时我们就僵住了,最后我们考虑到q有10000次之大,所以我们跑了个离线算法(LCA+tarjin),当然此题RMQ,ST表好像都是可以跑的。

    关于tarjin+LCA之后放一道裸题详细分析,此题代码就不给注释了。

    代码

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 typedef pair<int,int> PII;
      4 const int N=500+7;
      5 struct edge{
      6     int from,to,w;
      7 };
      8 struct askedge{
      9     int from,to,lca;
     10 }ae[N*N];
     11 edge mazee[N*N*4];
     12 int kfar[N*N];
     13 vector<int> G[N*N];
     14 vector<PII> pp[N*N];
     15 int tot=0;
     16 int n,m;
     17 void add_edge(int from,int to,int w)
     18 {
     19     mazee[tot].from=from;
     20     mazee[tot].to=to;
     21     mazee[tot].w=w;
     22     mazee[++tot].from=to;
     23     mazee[tot].to=from;
     24     mazee[tot].w=w;
     25 }
     26 void init()
     27 {
     28     for(int i=0;i<N*N;i++)
     29         kfar[i]=i;
     30 }
     31 bool cmp(edge a,edge b)
     32 {
     33     return a.w>b.w;
     34 }
     35 int Find(int x)
     36 {
     37     if(kfar[x]==x) return x;
     38     else return kfar[x]=Find(kfar[x]);
     39 }
     40 void Union(int x,int y)
     41 {
     42     x=Find(x);y=Find(y);
     43     if(x!=y) kfar[y]=x;
     44 }
     45 void kruskal()
     46 {
     47     sort(mazee,mazee+tot+1,cmp);
     48     int cnt=0;
     49     for(int i=0;i<n*m*4;i++)
     50     {
     51         edge &u=mazee[i];
     52         if(Find(u.from)!=Find(u.to))
     53         {
     54             Union(u.from,u.to);
     55             G[u.from].push_back(u.to);
     56             G[u.to].push_back(u.from);
     57             cnt++;
     58         }
     59         if(cnt==n*m-1) break;
     60     }
     61 }
     62 int far[N*N];
     63 int dist[N*N];
     64 int tarjinfind(int x)
     65 {
     66     if(far[x]==x) return x;
     67     else return far[x]=tarjinfind(far[x]);
     68 }
     69 void tarjinunion(int x,int y)
     70 {
     71     x=tarjinfind(x);y=tarjinfind(y);
     72     if(x!=y) far[y]=x;
     73 }
     74 void dfs(int now)
     75 {
     76     far[now]=now;
     77     for(int i=0;i<pp[now].size();i++)
     78     {
     79         PII &v=pp[now][i];
     80         if(dist[v.first]!=-1)
     81         {
     82             ae[v.second].lca=tarjinfind(v.first);
     83         }
     84     }
     85     for(int i=0;i<G[now].size();i++)
     86     {
     87         int &v=G[now][i];
     88         if(dist[v]==-1)
     89         {
     90             dist[v]=dist[now]+1;
     91             dfs(v);
     92             tarjinunion(now,v);
     93         }
     94     }
     95 }
     96 int main()
     97 {
     98     scanf("%d%d",&n,&m);
     99     for(int i=1;i<=n;i++)
    100     {
    101         for(int j=1;j<=m;j++)
    102         {
    103             char opd,opr;
    104             int down,right;
    105             scanf(" %c%d %c%d",&opd,&down,&opr,&right);
    106             if(opd!='X')
    107                 add_edge((i-1)*m+j,i*m+j,down);
    108             if(opr!='X')
    109                 add_edge((i-1)*m+j,(i-1)*m+j+1,right);
    110         }
    111     }
    112     init();
    113     kruskal();
    114     int q;
    115     scanf("%d",&q);
    116     for(int i=1;i<=q;i++)
    117     {
    118         int x1,y1,x2,y2;
    119         scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
    120         int u=m*(x1-1)+y1,v=m*(x2-1)+y2;
    121         pp[u].push_back(make_pair(v,i));
    122         pp[v].push_back(make_pair(u,i));
    123         ae[i]={u,v,-1};
    124     }
    125     memset(dist,-1,sizeof(dist));
    126     dist[1]=0;
    127     dfs(1);
    128     for(int i=1;i<=q;i++)
    129     {
    130         askedge &now=ae[i];
    131         printf("%d
    ",dist[now.from]+dist[now.to]-2*dist[now.lca]);
    132     }
    133     return 0;
    134 }

    后记

    赛时迅速的口A了这一题,奈何卡在求树上任两点距离,还算错了500*500,导致RE了十发。然后网上模板都是前向星,然而我不会,还是喜欢邻接表哎,所以赛后我自己改出了邻接表版本哈哈哈,希望以后能够继续多学习算法吧,口A码不出太难过了。向图论大师李老师致敬!

  • 相关阅读:
    无线鼠标换电池了
    Jython Interactive Servlet Console YOU WILL NEVER KNOW IT EXECLLENT!!! GOOD
    Accessing Jython from Java Without Using jythonc
    jython podcast cool isnt't it?
    Python里pycurl使用记录
    Creating an Interactive JRuby Console for the Eclipse Environment
    微软为AJAX和jQuery类库提供CDN服务
    Download A File Using Cygwin and cURL
    What is JMRI?这个是做什么用的,我真没看懂但看着又很强大
    用curl 发送指定的大cookie的http/https request
  • 原文地址:https://www.cnblogs.com/computer-luo/p/9622072.html
Copyright © 2011-2022 走看看