[BJOI2010]次小生成树
OJ题号:
BZOJ1977、COGS2453
题目大意:
给你一个无向连通图,求严格次小生成树。
思路:
对于一般次小生成树,我们有一个结论:一般次小生成树一定可以通过替换掉最小生成树某一条边得到。
因此对于一般次小生成树,我们只需要枚举不在MST上的每一条边,并枚举这条边对应两点路径上的所有边,尝试交换这两条边即可。
显然枚举树上每一条边的复杂度是O(n)的,会TLE,因此我们可以用树剖或者树上倍增的方法记录区间最大边。
然而这题要求的是严格次小生成树,所以万一你枚举的这两条边相等就WA了。
为了保险起见,我们再记录区间最大边的同时,还要记录区间严格次大边。
然后枚举的时候只要判断当前区间最大边是否和那条非树边相等,如果相等的话就取那条次大边即可。
一开始因为没有权限号就去COGS上交,然后随随便便就A了,还跑了Rank1。
但是据说那里数据比较水,就找q234rty借了权限号,去BZOJ上交,果然WA了。
随机了一个小数据,发现是最后倍增求最大树边的时候最后一层没跳上去。
去网上拉了一个程序对拍,发现无限WA。
拿了一个数据手动模拟了一遍,发现原来是网上的题解错了。。
1 #include<queue> 2 #include<cstdio> 3 #include<cctype> 4 #include<vector> 5 #include<algorithm> 6 inline int getint() { 7 register char ch; 8 while(!isdigit(ch=getchar())); 9 register int x=ch^'0'; 10 while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0'); 11 return x; 12 } 13 const long long inf=0x7fffffffffffffffll; 14 const int V=100001,logV=18; 15 inline int log2(const float x) { 16 return ((unsigned&)x>>23&255)-127; 17 } 18 class DisjointSet { 19 private: 20 int anc[V]; 21 int Find(const int &x) { 22 return x==anc[x]?x:anc[x]=Find(anc[x]); 23 } 24 public: 25 DisjointSet() { 26 for(register int i=0;i<V;i++) { 27 anc[i]=i; 28 } 29 } 30 void Union(const int &x,const int &y) { 31 anc[Find(x)]=Find(y); 32 } 33 bool isConnected(const int &x,const int &y) { 34 return Find(x)==Find(y); 35 } 36 }; 37 DisjointSet s; 38 struct Edge1 { 39 int u,v,w; 40 bool inMST; 41 bool operator < (const Edge1 &another) const { 42 return w<another.w; 43 } 44 }; 45 std::vector<Edge1> e1; 46 struct Edge { 47 int to,w; 48 }; 49 std::vector<Edge> e[V]; 50 inline void add_edge(const int &u,const int &v,const int &w) { 51 e[u].push_back((Edge){v,w}); 52 } 53 long long mst=0; 54 inline void kruskal() { 55 std::sort(e1.begin(),e1.end()); 56 for(register unsigned i=0;i<e1.size();i++) { 57 const int &u=e1[i].u,&v=e1[i].v,&w=e1[i].w; 58 if(s.isConnected(u,v)) continue; 59 s.Union(u,v); 60 add_edge(u,v,w); 61 add_edge(v,u,w); 62 e1[i].inMST=true; 63 mst+=w; 64 } 65 } 66 int anc[V][logV],max[V][logV],max2[V][logV]; 67 int dep[V]; 68 std::queue<int> q; 69 inline void bfs() { 70 q.push(1); 71 while(!q.empty()) { 72 const int x=q.front(); 73 q.pop(); 74 dep[x]=dep[anc[x][0]]+1; 75 for(register int i=1;i<=log2(dep[x]);i++) { 76 anc[x][i]=anc[anc[x][i-1]][i-1]; 77 max[x][i]=std::max(max[x][i-1],max[anc[x][i-1]][i-1]); 78 if(max[x][i-1]!=max[anc[x][i-1]][i-1]) { 79 max2[x][i]=std::min(max[x][i-1],max[anc[x][i-1]][i-1]); 80 } else { 81 max2[x][i]=std::max(max2[x][i-1],max2[anc[x][i-1]][i-1]); 82 } 83 } 84 for(register unsigned i=0;i<e[x].size();i++) { 85 const int &y=e[x][i].to; 86 if(y==anc[x][0]) continue; 87 anc[y][0]=x; 88 max[y][0]=e[x][i].w; 89 q.push(y); 90 } 91 } 92 } 93 inline int maxEdge(int x,int y,const int &w) { 94 int tmax=0; 95 while(dep[x]!=dep[y]) { 96 if(dep[x]<dep[y]) std::swap(x,y); 97 for(register int i=log2(dep[x]);i>=0;i--) { 98 if(dep[anc[x][i]]>=dep[y]) { 99 if(max[x][i]<w) { 100 tmax=std::max(tmax,max[x][i]); 101 } else if(max2[x][i]<w) { 102 tmax=std::max(tmax,max2[x][i]); 103 } 104 x=anc[x][i]; 105 } 106 } 107 } 108 if(x==y) return tmax; 109 for(register int i=log2(dep[x]);i>=0;i--) { 110 if(anc[x][i]!=anc[y][i]) { 111 if(max[x][i]<w) { 112 tmax=std::max(tmax,max[x][i]); 113 } else if(max2[x][i]<w) { 114 tmax=std::max(tmax,max2[x][i]); 115 } 116 if(max[y][i]<w) { 117 tmax=std::max(tmax,max[y][i]); 118 } else if(max2[y][i]<w) { 119 tmax=std::max(tmax,max2[y][i]); 120 } 121 x=anc[x][i],y=anc[y][i]; 122 } 123 } 124 if(max[x][0]<w) { 125 tmax=std::max(tmax,max[x][0]); 126 } else if(max2[x][0]<w) { 127 tmax=std::max(tmax,max2[x][0]); 128 } 129 if(max[y][0]<w) { 130 tmax=std::max(tmax,max[y][0]); 131 } else if(max2[y][0]<w) { 132 tmax=std::max(tmax,max2[y][0]); 133 } 134 return tmax; 135 } 136 int main() { 137 #ifndef ONLINE_JUDGE 138 freopen("secmst.in","r+",stdin); 139 freopen("secmst.out","w+",stdout); 140 #endif 141 int n=getint(),m=getint(); 142 for(register int i=1;i<=m;i++) { 143 const int u=getint(),v=getint(),w=getint(); 144 e1.push_back((Edge1){u,v,w,false}); 145 } 146 kruskal(); 147 bfs(); 148 long long ans=inf; 149 for(register unsigned i=0;i<e1.size();i++) { 150 if(e1[i].inMST) continue; 151 const int &u=e1[i].u,&v=e1[i].v,&w=e1[i].w; 152 ans=std::min(ans,mst-maxEdge(u,v,w)+w); 153 } 154 printf("%lld\n",ans); 155 #ifndef ONLINE_JUDGE 156 fclose(stdin),fclose(stdout); 157 #endif 158 return 0; 159 }