• 【Luogu P3398】 仓鼠找sugar


    题目大意:

    一棵树,判断 (a) 节点到 (b) 节点的最短路径是否与 (c) 节点到 (d) 节点的最短路径相交。

    正文:

    容易得到,若两条路径相交,那么某条路径的公共祖先位于另一条的路径里。既然这样,那问题就简化为了判断某条路径的公共祖先是否位于另一条的路径里。

    代码:

    {
    	q.push(root); d[root] = 1;
    	while (!q.empty())
    	{
    		int x = q.front(); 
    		q.pop();
    		for (int i = head[x]; i; i = next[i])
    		{
    			int y = to[i];
    			if (d[y]) continue;
    			d[y] = d[x] + 1;
    			f[y][0] = x;
    			for (int j = 1; j <= num; j++)
    				f[y][j] = f[f[y][j - 1]][j - 1];
    			q.push(y);
    		}
    	} 
    } 
    
    int lca (int x, int y)
    {
    	if (d[x] > d[y])
    	{
    		int t = x;
    		x = y;
    		y = t;
    	}
    	for (int i = num; i >= 0; i--)
    		if (d[f[y][i]] >= d[x])
    			y = f[y][i];
    	if (x == y) return x;
    	for (int i = num; i >= 0; i--)
    		if (f[x][i] != f[y][i])
    		{
    			x = f[x][i];
    			y = f[y][i];
    		}
    	return f[x][0];
    }
    
    int dis(int a, int b)
    {
    	int c = lca(a, b);
    	return abs(d[a] - d[c]) + abs(d[b] - d[c]);
    }
    
    int main()
    {
    	scanf ("%d%d", &n, &m); num = (int) (log2(n)) + 1;
    	for (int i = 1; i < n; i++)
    	{
    		int x, y;
    		scanf ("%d%d", &x, &y);
    		add(x, y), add(y, x);
    	}
    	bfs (1);
    	for (int i = 1; i <= m; i++)
    	{
    		int a, b, c, d;
    		scanf ("%d%d%d%d", &a, &b, &c, &d);
    		int x = lca(a, b), y = lca(c, d);
    		if(dis(x, c) + dis(x, d) == dis(c, d) ||
    		   dis(y, a) + dis(y, b) == dis(a, b))
    			puts("Y");
    		else puts("N");
    	}
    	return 0;
    }
    
  • 相关阅读:
    第二周学习总结
    第一周学习进度总结
    淘宝网质量属性分析
    软件架构师如何工作
    寒假学习记录第十六天
    寒假学习记录第十五天
    寒假学习记录第十四天
    寒假学习记录第十三天
    三.NFS存储服务
    二.Rsync备份服务
  • 原文地址:https://www.cnblogs.com/GJY-JURUO/p/13472330.html
Copyright © 2020-2023  润新知