# dyllalala

## [BeiJing2010组队][BZOJ 1977]次小生成树 Tree

MATO IS NO.1 的博客里对两种算法都有很好的解释，值得拥有:  (果然除我以外，所有自称傻 X 的都是神犇喵~)

MATO还讲了一个神级复杂度的次小生成树:  (请全部读完。如果被坑，后果自负)

  1 #include <cstdio>
2 #include <algorithm>
3 typedef long long llint;
4 const int inf=0x7FFFFFFF;
5 const int sizeOfN=100001;
6 const int sizeOfM=300003;
7
8 namespace IOspace
9 {
10     inline int getint()
11     {
12         register int num=0;
13         register char ch;
14         do ch=getchar(); while (ch<'0' || ch>'9');
15         do num=num*10+ch-'0', ch=getchar(); while (ch>='0' && ch<='9');
16         return num;
17     }
18     inline void putint(llint num, char ch='\n')
19     {
20         char stack[15];
21         register int top=0;
22         if (num==0) stack[top=1]='0';
23         for ( ;num;num/=10) stack[++top]=num%10+'0';
24         for ( ;top;top--) putchar(stack[top]);
25         if (ch) putchar(ch);
26     }
27 }
28
29 int N, M;
30
31 struct node {int u, v, c;};
32 node a[sizeOfM];
33 bool b[sizeOfM];
34 inline bool operator < (node i, node j)
35     {return i.c<j.c;}
36
37 struct edge {int point, dist; edge * next;};
38 edge MEM[sizeOfM], * PORT=MEM;
39 edge * E[sizeOfN];
40 inline edge * newedge(int _point, int _dist, edge * _next)
41     {edge * ret=PORT++; ret->point=_point; ret->dist=_dist; ret->next=_next; return ret;}
42 inline void build(int u, int v, int c)
43     {E[u]=newedge(v, c, E[u]); E[v]=newedge(u, c, E[v]);}
44
45 int r[sizeOfN];
46 int find(int x) {return r[x]==x?x:r[x]=find(r[x]);}
47
48 int f[sizeOfN][20], l[2][sizeOfN][20], h[sizeOfN];
49 bool vis[sizeOfN];
50 int top, stack[sizeOfN]; edge * temp[sizeOfN];
51 inline void search();
52
53 inline int max(int x, int y) {return x>y?x:y;}
54 inline int min(int x, int y) {return x<y?x:y;}
55 inline void swap(int & x, int & y) {int t=x; x=y; y=t;}
56 inline int lg(int x) {int i; for (i=0;x>1;i++) x>>=1; return i;}
57 inline int lowbit(int x) {return x & -x;}
58 inline int lca(int, int, int);
59 inline llint kurskal();
60 inline void prepare();
61 inline int calc();
62
63 int main()
64 {
65     llint ans=0;
66
67     N=IOspace::getint(); M=IOspace::getint();
68     for (int i=0;i<M;i++) a[i].u=IOspace::getint(), a[i].v=IOspace::getint(), a[i].c=IOspace::getint();
69
70     ans=kurskal();
71     prepare();
72     ans+=calc();
73
74     IOspace::putint(ans);
75
76     return 0;
77 }
78 inline void search()
79 {
80     f[1][0]=0; h[1]=1;
81     for (stack[++top]=1, temp[top]=E[1];top; )
82     {
83         int & u=stack[top]; edge *& i=temp[top];
84         if (!vis[u]) vis[u]=1;
85         for ( ;i;i=i->next) if (!vis[i->point])
86         {
87             f[i->point][0]=u; h[i->point]=h[u]+1;
88             l[0][i->point][0]=i->dist; l[1][i->point][0]=-inf;
89             stack[++top]=i->point; temp[top]=E[i->point];
90             break;
91         }
92         if (i) continue;
93         top--;
94     }
95 }
96 inline llint kurskal()
97 {
98     llint ret=0;
99     int tot=N-1;
100
101     std::sort(a, a+M);
102     for (int i=1;i<=N;i++) r[i]=i;
103
104     for (int i=0;i<M;i++)
105     {
106         int u=find(a[i].u), v=find(a[i].v);
107         if (u!=v)
108         {
109             build(a[i].u, a[i].v, a[i].c); ret+=a[i].c;
110             b[i]=1;
111             r[u]=v;
112             if (!--tot) break;
113         }
114     }
115
116     return ret;
117 }
118 inline void prepare()
119 {
120     search();
121     for (int j=1;j<20;j++)
122         for (int i=1;i<=N;i++) if (h[i]>=(1<<j))
123         {
124             f[i][j]=f[f[i][j-1]][j-1];
125             l[0][i][j]=l[0][i][j-1]; l[1][i][j]=l[1][i][j-1];
126             if (l[0][f[i][j-1]][j-1]>l[0][i][j]) l[1][i][j]=l[0][i][j], l[0][i][j]=l[0][f[i][j-1]][j-1];
127             else if (l[0][f[i][j-1]][j-1]<l[0][i][j])
128                 if (l[0][f[i][j-1]][j-1]>l[1][i][j]) l[1][i][j]=l[0][f[i][j-1]][j-1];
129         }
130 }
131 inline int lca(int u, int v, int x)
132 {
133     int ret=-1, dis;
134
135     if (h[u]<h[v]) swap(u, v);
136     while (dis=h[u]-h[v])
137     {
138         int up=lg(lowbit(dis));
139         ret=max(ret, l[l[0][u][up]==x][u][up]);
140         u=f[u][up];
141     }
142     if (u==v) return ret;
143
144     for (int i=19;i>=0;i--)
145         if (f[u][i]!=f[v][i])
146         {
147             ret=max(ret, l[l[0][u][i]==x][u][i]);
148             ret=max(ret, l[l[0][v][i]==x][v][i]);
149             u=f[u][i]; v=f[v][i];
150         }
151     ret=max(ret, l[l[0][u][0]==x][u][0]);
152     ret=max(ret, l[l[0][v][0]==x][v][0]);
153
154     return ret;
155 }
156 inline int calc()
157 {
158     int ret=inf;
159     for (int i=0;i<M;i++)
160         if (!b[i])
161             ret=min(ret, a[i].c-lca(a[i].u, a[i].v, a[i].c));
162     return ret;
163 }

posted on 2014-08-07 19:57  dyllalala  阅读(185)  评论(0编辑  收藏  举报