zoukankan      html  css  js  c++  java
  • 【BZOJ 2322】[BeiJing2011]梦想封印 利用"环基"+线性基特征值

      很容易想到离线加边并且把环和链拆开搞(就是对于每个终点求出起点到他的路径(其实就是dfs树),然后bzoj2115),而且维护也很简单,然而我们发现不同的终点可能得到相同的值,这就是我们遇到的最大的问题......继续观察,发现两个终点要么得到的值都不同要么得到的值都相同,所以我们就可以判断两个终点的链值的异或值(如果能被此时的"环基"搞出来就可以删掉一个),然后就60分......
      作为一名菜鸡,想到这里就去%题解了,发现我和题解的做法只有去重的时候不同......其实我们就是找到得到的值互不相同的终点的个数,也就是[对于目前的"环基",再插入链值,得到的线性基不同]的终点个数,然后我们发现对于每个终点,判断他们得到的线性基不同就是判断他们在"环基"里插入自己之后自己变成的值(需要经过上下消)不同,这样我们就能通过模拟插入过程得到每个值的"特征值",现在我们只需要找到特征值的种数就可以了(用个set就可以解决)!!!

    #include <set>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    char xB[(1<<15)+10],*xS,*xT;
    #define gtc (xS==xT&&(xT=(xS=xB)+fread(xB,1,1<<15,stdin),xS==xT)?0:*xS++)
    inline void read(int &x){
      register char ch=gtc;
      for(x=0;ch<'0'||ch>'9';ch=gtc);
      for(;ch>='0'&&ch<='9';x=(x<<1)+(x<<3)+ch-'0',ch=gtc);
    }
    typedef long long LL;
    inline void Read(LL &x){
      register char ch=gtc;
      for(x=0;ch<'0'||ch>'9';ch=gtc);
      for(;ch>='0'&&ch<='9';x=(x<<1)+(x<<3)+ch-'0',ch=gtc);
    }
    const int A=61,N=5010,M=20010;
    #define bin(a,b) (((a)>>(b))&1)
    std::set<LL>::iterator it;
    LL temp[N];
    int len;
    struct Gay{
      int size;LL gay[A];std::set<LL> st;
      inline LL trans(LL x,int begin){
        for(int i=begin;i>=0;--i)
          if(gay[i]&&bin(x,i))x^=gay[i];
        return x;
      }
      inline void put(LL x){st.insert(trans(x,A-1));}
      inline void insert(LL x){
        for(int i=A-1;i>=0;--i){
          if(!bin(x,i))continue;
          if(gay[i])x^=gay[i];
          else{gay[i]=x,++size,len=0;
            for(it=st.begin();it!=st.end();++it)
              temp[++len]=trans(*it,i);
            st.clear();
            for(int j=1;j<=len;++j)st.insert(temp[j]);
            break;}
        }
      }
      inline LL query(){
        return st.size()*(1LL<<size)-1;
      }
    }gay;
    struct V{int to,next;LL w;}c[M<<1];
    struct E{int a,b;LL c;}e[M];
    LL dis[N],ans[M];
    bool in[N],die[M];
    int head[N],t,n,m,Q,sort[M];
    inline void add(int x,int y,LL z){c[++t].to=y,c[t].next=head[x],head[x]=t,c[t].w=z;}
    inline void dfs(int x,int fa,LL val){
      in[x]=true,dis[x]=val,gay.put(val);
      for(int i=head[x];i;i=c[i].next)
        if(in[c[i].to])gay.insert(c[i].w^dis[x]^dis[c[i].to]);
        else dfs(c[i].to,x,val^c[i].w);
    }
    int main(){
      read(n),read(m),read(Q);
      register int i;int x;
      for(i=1;i<=m;++i)read(e[i].a),read(e[i].b),Read(e[i].c);
      for(i=1;i<=Q;++i)read(x),sort[i]=x,die[x]=true;
      for(i=1;i<=m;++i)if(!die[i])add(e[i].a,e[i].b,e[i].c),add(e[i].b,e[i].a,e[i].c);
      dfs(1,0,0);
      for(i=Q;i>0;--i){
        ans[i]=gay.query(),x=sort[i];
        add(e[x].a,e[x].b,e[x].c),add(e[x].b,e[x].a,e[x].c);
        if(in[e[x].a]==false&&in[e[x].b]==false)continue;
        if(in[e[x].a]&&in[e[x].b])gay.insert(dis[e[x].a]^dis[e[x].b]^e[x].c);
        else if(in[e[x].a])dfs(e[x].b,e[x].a,dis[e[x].a]^e[x].c);
        else dfs(e[x].a,e[x].b,dis[e[x].b]^e[x].c);
      }printf("%lld
    ",gay.query());
      for(i=1;i<=Q;++i)printf("%lld
    ",ans[i]);
      return 0;
    }
  • 相关阅读:
    (三)数据预处理过程简介
    (二)数据挖掘需要哪些技术
    (一) 什么是数据挖掘?
    怎样提问呢?
    什么是自我意识
    高效能人士的七个习惯
    “U”型读书法
    CMDB学习之一
    层级选择器
    css选择器
  • 原文地址:https://www.cnblogs.com/TSHugh/p/8379561.html
Copyright © 2011-2022 走看看