zoukankan      html  css  js  c++  java
  • [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
    ",ans);
    155     #ifndef ONLINE_JUDGE
    156         fclose(stdin),fclose(stdout);
    157     #endif
    158     return 0;
    159 } 
  • 相关阅读:
    软件开发项目文档模版
    Java Swing 非常漂亮的外观Nimbus使用方法
    周00王总监 宁波浦一的同仁们 有看见的进来
    冰川世界
    君住长江头,我住长江尾,日日思君不见君,共饮长江水
    可乐男孩被保送上大学
    变形金刚2
    爱无罪
    英语习惯口语简写
    看完了团长,我没有心理在去看《南京!南京!》
  • 原文地址:https://www.cnblogs.com/skylee03/p/7567092.html
Copyright © 2011-2022 走看看