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

话说这个[BeiJing2010组队]是个什喵玩意?

这是一道严格次小生成树,而次小生成树的做法是层出不穷的

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

  http://www.cppblog.com/MatoNo1/archive/2011/05/29/147627.aspx

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

  http://www.cppblog.com/MatoNo1/archive/2011/11/16/149812.html

如果你可以打开人人网的话(你懂的喵~),这也是篇很好的博文:

  http://blog.renren.com/share/235365847/6633394303 

该说的都在上面了,我就扔扔代码吧  (高能勿喷)

  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='
')
 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 }
本傻装B系列

写的比树套树还长,真是没脸见人了喵~

原文地址:https://www.cnblogs.com/dyllalala/p/3897946.html