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 } 
  • 相关阅读:
    一些业内有名的网站收集
    WCF重载
    FCKEditor fckconfig.js配置,添加字体和大小 附:中文字体乱码问题解决
    查询第几条到第几条的数据的SQL语句
    SPOJ 9939 Eliminate the Conflict
    UVA 10534 Wavio Sequence
    HDU 3474 Necklace
    POJ 2823 Sliding Window
    UVA 437 The Tower of Babylon
    UVA 825 Walking on the Safe Side
  • 原文地址:https://www.cnblogs.com/skylee03/p/7567092.html
Copyright © 2011-2022 走看看