German Collegiate Programming Contest 2018​ A. Attack on Alpha-Zet

题目链接https://nanti.jisuanke.com/t/28852

题目大意是 h*w 的平面,每两个点有且仅有一条路径,类似于封闭的联通空间,然后在这h*w个点中选取(标记为1~N)N个点(给了坐标),求从1号点按1~N的顺序走到N号点的路程。

练习赛的时候没有思路,队友说可以建树,但还是不清不楚没写出来。

做法是LCA。

将封闭的联通空间建树(点的位置与字符的位置有点麻烦),然后按顺序求两点的最近的公共祖先求深度得距离,最后得路程,算是一道LCA的模板。

  1 #include <bits/stdc++.h>
  2 #define fir first
  3 #define sec second
  4 #define EPS 1e-12
  5 using namespace std;
  6 
  7 typedef long long LL;
  8 typedef pair<int , int > pii;
  9 const int MAXN=1000000+6;
 10 const int DEG=20;
 11 
 12 struct Edge{
 13     int to,nxt;
 14 }edge[MAXN*2];
 15 int head[MAXN],tot;
 16 
 17 void addEdge(int u,int v){
 18     edge[tot].to=v;
 19     edge[tot].nxt=head[u];
 20     head[u]=tot++;
 21 }
 22 void init(){
 23     tot=0;
 24     memset(head,-1,sizeof(head));
 25 }
 26 int fa[MAXN][DEG];
 27 int deg[MAXN];
 28 
 29 void BFS(int root){
 30     queue< int > que;
 31     deg[root]=0;
 32     fa[root][0]=root;
 33     que.push(root);
 34     while(!que.empty()){
 35         int tmp=que.front();que.pop();
 36         for(int i=1;i<DEG;++i)
 37             fa[tmp][i]=fa[fa[tmp][i-1]][i-1];
 38         for(int i=head[tmp];i!=-1;i=edge[i].nxt){
 39             int v=edge[i].to;
 40             if(v==fa[tmp][0]) continue;
 41             deg[v]=deg[tmp]+1;
 42             fa[v][0]=tmp;
 43             que.push(v);
 44         }
 45     }
 46 }
 47 
 48 int LCA(int u,int v){
 49     if(deg[u]>deg[v]) swap(u,v);
 50     int hu=deg[u],hv=deg[v];
 51     int tu=u,tv=v;
 52     for(int det=hv-hu,i=0;det;det>>=1,++i)
 53         if(det&1) tv=fa[tv][i];
 54     if(tu==tv) return tu;
 55     for(int i=DEG-1;i>=0;--i){
 56         if(fa[tu][i]==fa[tv][i])
 57             continue;
 58         tu=fa[tu][i];
 59         tv=fa[tv][i];
 60     }
 61     return fa[tu][0];
 62 }
 63 
 64 char maze[1010][2020];
 65 int H,W;
 66 
 67 void Judge(int cur,int xx,int yy){
 68     int i=xx,j=(yy+1)/2;
 69     if(maze[xx-1][yy]!='_'){
 70         int to=(i-2)*W+j;
 71         addEdge(cur,to);
 72     }
 73     if(maze[xx][yy]!='_'){
 74         int to=(i)*W+j;
 75         addEdge(cur,to);
 76     }
 77     if(maze[xx][yy-1]!='|'){
 78         int to=(i-1)*W+j-1;
 79         addEdge(cur,to);
 80     }
 81     if(maze[xx][yy+1]!='|'){
 82         int to=(i-1)*W+j+1;
 83         addEdge(cur,to);
 84     }
 85 }
 86 
 87 LL caldist(int u,int v){
 88     int ace=LCA(u,v);
 89     return deg[u]+deg[v]-2*deg[ace];
 90 }
 91 
 92 int main()
 93 {
 94     init();
 95     scanf("%d%d%*c",&H,&W);
 96     for(int i=0;i<=H;++i){
 97         scanf("%[^\n]%*c",maze[i]);
 98     }
 99     for(int i=1;i<=H;++i){
100         for(int j=1;j<=W;++j){
101             int tmp=(i-1)*W+j;
102             int xx=i,yy=2*j-1;
103             Judge(tmp,xx,yy);
104         }
105     }
106     BFS(1);
107     LL ans=0;
108     int N,xi,yi;
109     scanf("%d%d%d",&N,&xi,&yi);
110     int old=(xi-1)*W+yi,aft;
111     for(int i=1;i<N;++i){
112         scanf("%d%d",&xi,&yi);
113         aft=(xi-1)*W+yi;
114         ans+=caldist(old,aft);
115         old=aft;
116     }
117     printf("%lld\n",ans);
118     return 0;
119 }
View Code

 

posted on 2018-07-21 18:18  Emiya_Kiritsugu  阅读(243)  评论(0编辑  收藏  举报

导航