BZOJ1787 [Ahoi2008]Meet 紧急集合

水题 求出三个人每两个间的LCA,然后最小花费就是两两点之间的路径长度之和除以2

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 using namespace std;
 5 const int maxn = 500005;
 6 struct edge{
 7     int v,next;
 8 }e[maxn*2];
 9 struct ask{
10     int v,next,lca,d,u;
11 }q[maxn*6];
12 int head[maxn],cnt,head1[maxn],cnt_ask;
13 int d[maxn],fa[maxn],vis[maxn];
14 void init()
15 {
16     memset(head,-1,sizeof(head));
17     memset(head1,-1,sizeof(head1));
18     memset(vis,0,sizeof(vis));
19     cnt = cnt_ask = d[1] = 0;
20 }
21 void add(int u,int v)
22 {
23     e[cnt].v = v;
24     e[cnt].next = head[u];
25     head[u] = cnt++;
26 }
27 void add_ask(int u,int v)
28 {
29     q[cnt_ask].v = v;
30     q[cnt_ask].u = u;
31     q[cnt_ask].next = head1[u];
32     head1[u] = cnt_ask++;
33 }
34 void dfs(int rt,int father)
35 {
36     for(int i = head[rt];i!=-1;i=e[i].next)if(e[i].v!=father)
37     {
38         d[e[i].v] = d[rt]+1;
39         dfs(e[i].v,rt);
40     }
41 }
42 int findd(int x)
43 {
44     int rt = x;
45     while(rt!=fa[rt])rt = fa[rt];
46     while(x!=rt){
47         int t = fa[x];
48         fa[x] = rt;
49         x = t;
50     }
51     return rt;
52 }
53 void lca(int rt,int father){
54     fa[rt] = rt;
55     for(int i = head[rt];i!=-1;i=e[i].next)if(father!=e[i].v){
56         lca(e[i].v,rt);
57         fa[e[i].v] = rt;
58     }
59     vis[rt] = 1;
60     for(int i = head1[rt];i!=-1;i=q[i].next)if(vis[q[i].v]){
61         q[i].lca = q[i^1].lca = findd(q[i].v);
62     }
63 }
64 int main()
65 {
66     //freopen("in.txt","r",stdin);
67     int n,m;scanf("%d%d",&n,&m);
68     init();
69     for(int i = 1;i<n;++i){
70         int u,v;scanf("%d%d",&u,&v);
71         add(u,v);add(v,u);
72     }
73     dfs(1,1);
74     for(int i = 1;i<=m;++i){
75         int u,v,w;scanf("%d%d%d",&u,&v,&w);
76         add_ask(u,v);add_ask(v,u);
77         add_ask(u,w);add_ask(w,u);
78         add_ask(w,v);add_ask(v,w);
79     }
80     lca(1,1);
81     for(int i = 0;i<cnt_ask;++i)q[i].d = d[q[i].u]+d[q[i].v]-2*d[q[i].lca];
82     for(int i = 0;i<cnt_ask;i+=6){
83         int ans1,ans2 = (q[i].d+q[i+2].d+q[i+4].d)/2;
84         ans1 = max(d[q[i].lca],max(d[q[i+2].lca],d[q[i+4].lca]));
85         for(int j = i;j<i+5;j+=2)
86             if(ans1==d[q[j].lca]){
87                 ans1 = q[j].lca;break;
88             }
89         printf("%d %d\n",ans1,ans2);
90     }
91     return 0;
92 }
时间: 2024-10-10 15:16:30

BZOJ1787 [Ahoi2008]Meet 紧急集合的相关文章

[bzoj1787][Ahoi2008]Meet 紧急集合(lca)

传送门 可以看出,三个点两两之间的lca会有一对相同,而另一个lca就是聚集点. 然后搞搞就可以求出距离了. ——代码 1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #define MAXN 1000001 5 6 using namespace std; 7 8 int n, m, cnt, ans; 9 int head[MAXN], to[MAXN], next[MAXN], de

【块状树】【LCA】bzoj1787 [Ahoi2008]Meet 紧急集合

分块LCA什么的,意外地快呢…… 就是对询问的3个点两两求LCA,若其中两组LCA相等,则答案为第三者. 然后用深度减一减什么的就求出距离了. 1 #include<cstdio> 2 #include<algorithm> 3 #include<cmath> 4 using namespace std; 5 #define maxn 500001 6 struct Graph 7 {int v[maxn<<1],first[maxn<<1],n

bzoj 1787: [Ahoi2008]Meet 紧急集合

1787: [Ahoi2008]Meet 紧急集合 Time Limit: 20 Sec  Memory Limit: 162 MBSubmit: 3016  Solved: 1344[Submit][Status][Discuss] Description Input Output Sample Input 6 4 1 2 2 3 2 4 4 5 5 6 4 5 6 6 3 1 2 4 4 6 6 6 Sample Output 5 2 2 5 4 1 6 0 HINT Source Day1

【BZOJ-1787】Meet紧急集合 倍增LCA

1787: [Ahoi2008]Meet 紧急集合 Time Limit: 20 Sec  Memory Limit: 162 MBSubmit: 2259  Solved: 1023[Submit][Status][Discuss] Description Input Output Sample Input 6 4 1 2 2 3 2 4 4 5 5 6 4 5 6 6 3 1 2 4 4 6 6 6 Sample Output 5 2 2 5 4 1 6 0 HINT Source Day1

1787: [Ahoi2008]Meet 紧急集合

1787: [Ahoi2008]Meet 紧急集合 Description Input Output Sample Input 6 4 1 2 2 3 2 4 4 5 5 6 4 5 6 6 3 1 2 4 4 6 6 6 Sample Output 5 2 2 5 4 1 6 0 HINT 题解: n-1条边,很明显这是一棵树 那么题目就是求3个点的LCA 我们将3个点x,y,z分别求出x,y的LCA,设为a,x,z的为b,y,z的为c 则a,b,c 3个点中必有两个相等,答案就是另外一个(自

bzoj 1787 [Ahoi2008]Meet 紧急集合(1832 [AHOI2008]聚会)

1787: [Ahoi2008]Meet 紧急集合 Time Limit: 20 Sec  Memory Limit: 162 MBSubmit: 1841  Solved: 857[Submit][Status][Discuss] Description Input Output Sample Input 6 4 1 2 2 3 2 4 4 5 5 6 4 5 6 6 3 1 2 4 4 6 6 6 Sample Output 5 2 2 5 4 1 6 0 HINT Source Day1

BZOJ 1787: [Ahoi2008]Meet 紧急集合( 树链剖分 )

这道题用 LCA 就可以水过去 , 但是我太弱了 QAQ 倍增写LCA总是写残...于是就写了树链剖分... 其实也不难写 , 线段树也不用用到 , 自己YY一下然后搞一搞就过了...速度还挺快的好像= = #9 ---------------------------------------------------------------------------------- #include<cstdio> #include<cstring> #include<algori

【bzoj1787】[Ahoi2008]Meet 紧急集合

求三个结点到一个结点距离之和最小的结点以及距离和 求出两两lca,其中有两个相同,答案则为另一个 感觉就是一大暴力... 1 #include<algorithm> 2 #include<iostream> 3 #include<cstdlib> 4 #include<cstring> 5 #include<cstdio> 6 #include<cmath> 7 #include<queue> 8 using namesp

【Ahoi2008】【lca】【bzoj1787】Meet 紧急集合

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1787 题解: 求出三个点两两之间的lca会发现有两个是一样的,然后我们选那个不一样的就好了. #include<iostream> #include<cstdio> #include<cmath> #include<cstring> using namespace std; struct use{ int st,en; }b[5000001]; in