LCA 笔记

简述这几天的LCA 心得:

LCA有两种做法:离线 or 在线

先学的离线;

原理博客很多。

我写得两道题,已经模板。

HDU:http://acm.hdu.edu.cn/showproblem.php?pid=2586

HDU :http://acm.hdu.edu.cn/showproblem.php?pid=2874 2874;

之前一份板子:

 1 #pragma comment(linker, "/STACK:10240000000,10240000000")  
 2 
 3 #include<iostream>
 4 #include<stdio.h>
 5 #include<string.h>
 6 #include<cmath>
 7 #include<algorithm>
 8 #include<string>
 9 #include<vector>
10 using namespace std;
11 
12 #define N 51111
13 struct node
14 {
15     int v,w;
16 
17     node(int vv,int ww)
18     {
19        v=vv;
20        w=ww;
21     }
22 };
23 int f[N],dis[N],ans[N],vis[N],n;
24 vector<node>mp[N];
25 vector<node>q[N];
26 
27 int find(int x)
28 {
29     if (f[x]!=x)  f[x]=find(f[x]);
30     return f[x];
31 }
32 
33 void lca(int u)
34 {
35     for (int i=0;i<mp[u].size();i++)
36     {
37         int v=mp[u][i].v;
38         if (vis[v]) continue;
39         vis[v]=1;
40 
41         dis[v]=dis[u]+mp[u][i].w;
42         lca(v);
43         f[v]=u;
44         for (int j=0;j<q[v].size();j++)
45         {
46             int c=q[v][j].v;
47             if (vis[c]&&ans[q[v][j].w]==-1)
48             {
49                 if (v==c) ans[q[v][j].w]=0;
50                 else ans[q[v][j].w]=dis[v]+dis[c]-2*dis[find(c)];
51             }
52         }
53     }
54 }
55 
56 int main()
57 {
58     int T;
59     scanf("%d",&T);
60     while (T--)
61     {
62         int m;
63         scanf("%d%d",&n,&m);
64         for (int i=1;i<=n;i++)
65         {
66             mp[i].clear();
67             q[i].clear();
68             ans[i]=-1;
69             f[i]=i;
70             vis[i]=0;
71         }
72         for (int i=1;i<n;i++)
73         {
74             int a,b,c;
75             scanf("%d%d%d",&a,&b,&c);
76             mp[a].push_back(node(b,c));
77             mp[b].push_back(node(a,c));
78         }
79         for (int i=1;i<=m;i++)
80         {
81             int a,b;
82             scanf("%d%d",&a,&b);
83             q[a].push_back(node(b,i));
84             q[b].push_back(node(a,i));
85         }
86         vis[1]=1;
87         dis[1]=0;
88         lca(1);
89 
90         for (int i=1;i<=m;i++)
91             printf("%d\n",ans[i]);
92     }
93     return 0;
94 }
View Code

是有问题的,但是数据弱所以没爆出来。

正确形式:

 1 #include<iostream>
 2 #include<stdio.h>
 3 #include<string.h>
 4 #include<cmath>
 5 #include<algorithm>
 6 #include<string>
 7 #include<vector>
 8 using namespace std;
 9 
10 #define N 51111
11 struct node
12 {
13     int v,w;
14 
15     node(int vv,int ww)
16     {
17        v=vv;
18        w=ww;
19     }
20 };
21 int f[N],dis[N],ans[N],vis[N],n;
22 vector<node>mp[N];
23 vector<node>q[N];
24 
25 int find(int x)
26 {
27     if (f[x]!=x)  f[x]=find(f[x]);
28     return f[x];
29 }
30 
31 void lca(int u)
32 {
33     for (int i=0;i<mp[u].size();i++)
34     {
35         int v=mp[u][i].v;
36         if (vis[v]) continue;
37         vis[v]=1;
38 
39         dis[v]=dis[u]+mp[u][i].w;
40         lca(v);
41         f[v]=u;
42     }
43         for (int j=0;j<q[u].size();j++)
44         {
45             int c=q[u][j].v;
46             if (vis[c]&&ans[q[u][j].w]==-1)
47             {
48                 if (u==c) ans[q[u][j].w]=0;
49                 else ans[q[u][j].w]=dis[u]+dis[c]-2*dis[find(c)];
50             }
51         }
52 
53 }
54 
55 int main()
56 {
57     int T;
58     scanf("%d",&T);
59     while (T--)
60     {
61         int m;
62         scanf("%d%d",&n,&m);
63         for (int i=1;i<=n;i++)
64         {
65             mp[i].clear();
66             q[i].clear();
67             ans[i]=-1;
68             f[i]=i;
69             vis[i]=0;
70         }
71         for (int i=1;i<n;i++)
72         {
73             int a,b,c;
74             scanf("%d%d%d",&a,&b,&c);
75             mp[a].push_back(node(b,c));
76             mp[b].push_back(node(a,c));
77         }
78         for (int i=1;i<=m;i++)
79         {
80             int a,b;
81             scanf("%d%d",&a,&b);
82             q[a].push_back(node(b,i));
83             q[b].push_back(node(a,i));
84         }
85         vis[1]=1;
86         dis[1]=0;
87         lca(1);
88 
89         for (int i=1;i<=m;i++)
90             printf("%d\n",ans[i]);
91     }
92     return 0;
93 }
View Code

可以仔细体验差别。

因为 在其中吃了大亏。HDU 2874 (都是简单题)卡了三天 。想想算法没错 ,果然是板子的问题。

换一种写法也可以,询问在递归前面也可以。

  1 #include<iostream>
  2 #include<stdio.h>
  3 #include<string.h>
  4 #include<cmath>
  5 #include<algorithm>
  6 #include<string>
  7 #include<vector>
  8 using namespace std;
  9 
 10 #define N 21111
 11 typedef long long ll;
 12 struct node
 13 {
 14     int v,w;
 15     node(int vv=0,int ww=0)
 16     {
 17        v=vv;
 18        w=ww;
 19     }
 20 };
 21 
 22 int f[N];
 23 int ans[1110000],dis[N];
 24 int vis[N],mark[N];
 25 
 26 vector<node>mp[N];
 27 vector<node>q[N];
 28 
 29 int find(int x)
 30 {
 31     if (f[x]!=x)  f[x]=find(f[x]);
 32     return f[x];
 33 }
 34 
 35 void lca(int u)
 36 {
 37 
 38     for (int i=0;i<q[u].size();i++)
 39     {
 40         int c=q[u][i].v;
 41         int w=q[u][i].w;
 42         if (vis[c]&&ans[w]==-1&&mark[find(c)]!=1)
 43         {
 44             ans[w]=dis[u]+dis[c]-2*dis[find(c)];
 45         }
 46     }
 47 
 48       for (int i=0;i<mp[u].size();i++)
 49     {
 50         int v=mp[u][i].v;
 51         if (vis[v]) continue;
 52         vis[v]=1;
 53         dis[v]=dis[u]+mp[u][i].w;
 54         lca(v);
 55         f[v]=u;
 56         /*
 57        for (int j=0;j<q[v].size();j++)
 58         {
 59             int c=q[v][j].v;
 60             int w=q[v][j].w;
 61             if (vis[c]&&ans[w]==-1&&mark[find(c)]!=1)
 62             {
 63                 // if (v==c) ans[w]=0;
 64                 // else
 65                  ans[w]=dis[v]+dis[c]-2*dis[find(c)];
 66             }
 67         }
 68         */
 69 
 70     }
 71 }
 72 
 73 int main()
 74 {
 75     // freopen("input.txt","r",stdin);
 76     // freopen("output1.txt","w",stdout);
 77      int n,m,C;
 78      while (scanf("%d%d%d",&n,&m,&C)!=EOF)
 79      {
 80         for (int i=0;i<=n;i++)
 81         {
 82             f[i]=i;
 83             mp[i].clear();
 84             q[i].clear();
 85             vis[i]=0;
 86             dis[i]=0;
 87             mark[i]=0;
 88         }
 89         for (int i=1;i<=C;i++) ans[i]=-1;
 90         for (int i=1;i<=m;i++)
 91         {
 92             int a,b,c;
 93             scanf("%d%d%d",&a,&b,&c);
 94             mp[a].push_back(node(b,c));
 95             mp[b].push_back(node(a,c));
 96         }
 97         for (int i=1;i<=C;i++)
 98         {
 99             int a,b;
100             scanf("%d%d",&a,&b);
101             q[a].push_back(node(b,i));
102             q[b].push_back(node(a,i));
103         }
104 
105         for (int i=1;i<=n;i++)
106         if (!vis[i])
107         {
108             vis[i]=1;
109             dis[i]=0;
110             lca(i);
111             mark[i]=1;
112         }
113 
114          for (int i=1;i<=n;i++)
115          for (int j=0;j<q[i].size();j++)
116          {
117              int u=i;
118              int v=q[i][j].v;
119              int w=q[i][j].w;
120              if (find(u)!=find(v)) ans[w]=-1;
121          }
122 
123 
124             for (int i=1;i<=C;i++)
125             if (ans[i]==-1) printf("Not connected\n");
126             else printf("%d\n",ans[i]);
127 
128     }
129     return 0;
130 }

 

posted on 2014-12-30 15:00  forgot93  阅读(187)  评论(0编辑  收藏  举报

导航