[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='\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 }
写的比树套树还长,真是没脸见人了喵~