codeforces D. Misha, Grisha and Underground(LCA)

来源:互联网 发布:贪心算法的实例 编辑:程序博客网 时间:2024/06/06 12:52

 题目链接

D. Misha, Grisha and Underground

分析

LCA 模板题
对于三个顶点 a,b,c 因为,我们只需要找到他们的公共点,然后,公共点到各自距离子和的最大值就是ans
u公共点怎么找呢?三个顶点会产生3个LCA,一定有两个顶点的公共祖先是一样的,另外一个就是公共点,因此只需要对3个顶点异或一下就好了(还有这种操作~~~~)

AC code

http://codeforces.com/contest/832/submission/28877988

#include<bits/stdc++.h>#define pb push_back#define mp make_pair#define PI acos(-1)#define fi first#define se second#define INF 0x3f3f3f3f#define INF64 0x3f3f3f3f3f3f3f3f#define random(a,b) ((a)+rand()%((b)-(a)+1))#define ms(x,v) memset((x),(v),sizeof(x))using namespace std;const int MOD = 1e9+7;const double eps = 1e-8;typedef long long LL;typedef long double DB;typedef pair<int,int> PII;const int maxn = 1e6+10;const int MAX_V = 1e5+10;std::vector<int> G[maxn];const int LOG_V = 20;int n;int root=1;//树根int par[MAX_V][LOG_V];//每一个节点的(2^k)个祖先int depth[MAX_V];  //找节点的深度和父亲.  void dfs(int v,int p,int d){    par[v][0] = p;    depth[v] = d;    for(int i=0 ; i<G[v].size() ; ++i)      if(G[v][i]!=p)dfs(G[v][i],v,d+1);//这是树,边的关系只有父亲节点和子孙.  }  //预处理,倍增  void init(){      //ms(par,-1);    dfs(root,-1,0);    for(int k = 0 ; k<LOG_V-1 ; ++k){//过剩处理不影响结果.      for(int i = 1 ; i<=n ; ++i)      par[i][k+1] = par[i][k] ==-1?-1 :par[par[i][k]][k];    }  }  int lca(int u,int v){    //跑到同一高度.    if(depth[u]>depth[v])swap(u,v);    for(int k=0 ; k<LOG_V ; ++k)      if(((depth[v]-depth[u])>>k) & 1)//差的二进制走        v = par[v][k];    if(u==v)return u;    for(int k= LOG_V-1 ; k>=0 ; k--)      if(par[u][k]!=par[v][k]){//避免跳过最近祖先        u = par[u][k];        v = par[v][k];      }    return par[u][0];  }int dis(int u,int v){    return depth[u] + depth[v] - 2* depth[lca(u,v)];}void add_edge(int u,int v) {    G[u].pb(v);G[v].pb(u);}int main() {    std::ios::sync_with_stdio(false);    std::cin.tie(0);    int q;    cin>>n>>q;    for(int i=0 ; i<n-1 ; ++i){        int p;cin>>p;        add_edge(i+2,p);    }    init();    while (q--) {        int a,b,c;        cin>>a>>b>>c;        int v1 = lca(a,b);        int v2 = lca(a,c);        int v3 = lca(b,c);        // std::cout << v1 <<" " <<v2 <<" " <<v3 << '\n';        int v = v1 ^v2 ^v3;        std::cout << max({dis(v,a),dis(v,b),dis(v,c)})+1 << '\n';    }    return 0;}

总结

LCA 的模板居然出现问题了,让我找了好一会儿~,,,,

for(int k = 0 ; k<LOG_V-1 ; ++k){//过剩处理不影响结果.      for(int i = 1 ; i<=n ; ++i)      par[i][k+1] = par[i][k] ==-1?-1 :par[par[i][k]][k];    }

啊当这个k超出范围的时候,由于二位数组是一块连续内存,所以第一个元素会被溢出的元素修改掉

原创粉丝点击