zoukankan      html  css  js  c++  java
  • UESCT 1219 题解

    题意:在没有自环的连通图中找一条回路,使路径上所有边权xor值最大(同一条路走过多次需要重复计算)

    2<=N<=50000;1<=M<=100000;0<=wi<=260-1.1~30组数据,4000MS

    xor高斯消元:在图中寻找环,并计算找到的环的总xor值(每条边、每个点都只用走一次,显然没找出来的环可以用找到的所有环的xor值的子集的xor值结果表示),显然每条回路答案都可以用这些所有环的xor值的子集的xor值结果表示,则对所有环的xor值进行xor高斯消元。

    说起这个xor高斯消元就厉害了,可用于计算一个数集所有子集的数的xor值的最大值:将所有数拆分成二进制形式,列出xor方程组——对每一个二进制位都列出一个方程组,右边常数项为1,从高位向低位判断是否相容,相容则该位可以为1,不相容则将这条方程删去,该位为0。

    具体来说,以a[i][j]表示第j个数的第i个二进制位,从上至下,在每行寻找不为0的系数,若有,则该方程满足条件,同时消去下面方程的该变元(某条方程该处系数为1,则对这条方程进行xor消元),若没有,但常数项为0,方程亦满足条件,常数项为1则不满足条件,满足条件则ans+=1ll<<i;由于我们从高位向低位做,不满足条件则抽去该方程,所以能保证xor值最大(贪心思想),复杂度O(环*环*61)

     

    #include<cstdio>
    #include<cstring>
    #include<vector>
    #include<iostream>
    using namespace std;
    
    const int maxm=200000;
    const int maxn=100000;
    int t,u,v,n,m,sb,tot;
    long long x,y,w,tmp;
    long long ans;
    int head[maxn];
    long long edge[2*maxm][3];
    bool ve[2*maxm]; 
    vector<long long> huan;
    bool vis[maxn];
    int gs[70][maxn];
    long long cf[maxn];
    
    void add_edge(int x,int y,long long w){
        edge[++tot][0]=y;edge[tot][1]=w;edge[tot][2]=head[x];head[x]=tot;
        edge[++tot][0]=x;edge[tot][1]=w;edge[tot][2]=head[y];head[y]=tot;
    }
    
    void dfs(int fa,int v,long long xo){
        cf[v]=xo;vis[v]=true;
        for (int i=head[v];i;i=edge[i][2]) if (edge[i][0]!=fa && !ve[i]) {
            ve[i]=true;ve[i^1]=true;
            if (vis[edge[i][0]]) huan.push_back(xo^cf[edge[i][0]]^edge[i][1]);
                else dfs(v,edge[i][0],xo^edge[i][1]);    
        }
    }
    
    void gauss(){
        bool flag;
        for (int i=1;i<=61;++i){
            flag=false;
            for (int j=1;j<=sb;++j)
                if (gs[i][j]) {
                    ans+=1ll<<(61-i);
                    for (int k=i+1;k<=61;++k) if (gs[k][j]) 
                        for (int l=1;l<=sb+1;++l) gs[k][l]^=gs[i][l];
                    flag=true;break;
                }
            if (!flag && gs[i][sb+1]==0) {ans+=1ll<<(61-i);}
        }
    }
    
    int main(){
        scanf("%d",&t);
        for (int q=1;q<=t;++q){
            scanf("%d%d",&n,&m);
            memset(ve,false,sizeof(ve));memset(head,0,sizeof(head));
            tot=-1;
            huan.clear();
            for (int i=1;i<=m;++i){
                scanf("%d%d%lld",&u,&v,&w);
                add_edge(u,v,w);
            }
            memset(vis,false,sizeof(vis));
            dfs(-1,1,0);memset(gs,0,sizeof(gs));sb=huan.size();
            for (int i=0;i<sb;i++){
                x=huan[i];
                for (int j=60;j>=0;--j) if (x & 1ll<<(j)){
                    gs[61-j][i+1]=1;
                } 
            }
            for (int i=0;i<=61;++i) gs[i][sb+1]=1;
            ans=0;
            gauss();
            printf("Case #%d: %lld
    ",q,ans);            
        }
        return 0;
    }
  • 相关阅读:
    fiddler抓取java系程序的网络通信
    ZOJ 2724 Windows Message Queue(优先队列)
    FZU 电动车通行证制度
    Havel定理
    Catch That Cow
    Trie树
    zoj 2876 Phone List
    zoj 2420
    getchar
    zoj 1315 Excuses, Excuses!
  • 原文地址:https://www.cnblogs.com/terra/p/6992547.html
Copyright © 2011-2022 走看看