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 }

 

posted on 2015-07-31 22:27  round_0  阅读(155)  评论(0编辑  收藏  举报

导航