zoukankan      html  css  js  c++  java
  • [HEOI2012]朋友圈

    [HEOI2012]朋友圈

    0x01 题意

    有俩国家,国家里的每一个人有一个友善值,在A国,当且仅当两个人的友善值异或起来为奇数时两人为朋友,在B国,当且仅当两个人的友善值异或起来为偶数或着两个人的友善值或起来的二进制数有奇数个1时,两人为朋友,AB国之间有一些人是朋友,求该图的最大团。

    0x02 解

    建图时发现的性质:

    众所周知,异或是不进位的加法。所以在A国,友善值是奇数的人和友善值是偶数的人是朋友,在B国,友善值同是奇数或同是偶数的人是朋友,以及两人友善值或起来的二进制数有奇数个1的人是朋友

    如果要求最大团:

    A国里最多选2个人,B国可以看作一个二分图,左部点为友善值是奇数的,右部点为友善值是偶数的,之间有一些边相连

    可以暴力判A国人,B国用匈牙利算法解决,这里有一个优化叫时间戳优化

    时间戳优化:

    原来的匈牙利算法每次找增广路时都要把vis memset一下,是(O(n))的复杂度,如果用一个整型数组来代替vis,每次改变一下基准值num,即

    [vis[v]=1 ightarrow vis[v]=num ]

    [vis[v]=0 ightarrow vis[v] eq num ]

    实现(O(1))初始化

    0x03 码

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<string>
    #include<cmath>
    #include<vector>
    #include<map>
    #include<queue>
    #include<deque>
    #include<set>
    #include<stack>
    #include<bitset>
    #include<cstring>
    #define ll long long
    #define max(a,b) ((a>b)?a:b)
    #define min(a,b) ((a<b)?a:b)
    using namespace std;
    const int INF=0x3f3f3f3f,E=10000000,N=3310;
    
    inline int read(){
        int x=0,y=1;char c=getchar();
        while (c<'0'||c>'9') {if (c=='-') y=-1;c=getchar();}
        while (c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
        return x*y;
    }
    
    int e[E],ne[E],h[N],v[N],idx;
    int t,n1,n2,m,a[N],b[N];
    int mapp[3310][3310];
    
    void add(int a,int b){
        e[idx]=b,ne[idx]=h[a],h[a]=idx++;
    }
    
    int match[N],num,all,tot,ans,id;
    int st[N],bl[N];
    
    bool find(int x){
    	for(int i=h[x];~i;i=ne[i]){
    		int j=e[i];
            if(st[j]!=num&&bl[j]==id){
    			st[j]=num;
                if(match[j]==0||find(match[j])){
    				match[j]=x;
                    return true;
                }
            }
        }
        
        return false;
    }
    
    bool qs(int x){
        int tot=0;
        while(x){if(x&1) tot++;x>>=1;}
        if(tot%2==1) return 1;
        return 0;
    }
    
    
    int main(){
    
        memset(h,-1,sizeof h);
    
        t=read();
        while(t--){
            n1=read();n2=read();m=read();
            for(int i=1;i<=n1;i++) a[i]=read();
            for(int i=1;i<=n2;i++) b[i]=read();
            for(int i=1;i<=n2;i++) if(b[i]&1)
                for(int j=1;j<=n2;j++){
                    if(!(b[j]&1)&&(!qs(b[i]|b[j])))
                    add(i,j);
                }
            for(int i=1;i<=m;i++){
                int x,y;
                x=read(),y=read();
                mapp[x][y+n1]=mapp[y+n1][x]=1;
            }
            for(int i=1;i<=n2;i++){
                if(b[i]&1){num++;if(find(i)) ans++;}
            }
            ans=n2-ans;
            for(int i=1;i<=n1;i++){
                id++;
                tot=0;all=0;
                memset(match,0,sizeof match);
                for(int j=1;j<=n2;j++)
                    if(mapp[i][j+n1]) bl[j]=id,all++;
                for(int j=1;j<=n2;j++)
                    if(bl[j]==id&&(b[j]&1)){num++;if(find(j)) tot++;}
                ans=max(ans,all-tot+1);
            }
            for(int i=1;i<=n1;i++){
                for(int j=i+1;j<=n1;j++){
                    if((a[i]^a[j])&1){
                        memset(match,0,sizeof match);
                        id++;
                        tot=0;all=0;
                        for(int k=1;k<=n2;k++)
                            if(mapp[i][k+n1]&&mapp[j][k+n1]) bl[k]=id,all++;
                        for(int k=1;k<=n2;k++)
                            if(bl[k]==id&&(b[k]&1)){num++;if(find(k)) tot++;}
                        ans=max(ans,all-tot+2);
                    }
                }
            }
            cout<<ans<<endl;
        }
        
        return 0;
    }
    
  • 相关阅读:
    jenkins配置html报告
    JMeter并发测试(设置集合点)
    jmeter压力测试 设置一秒发送一次请求,一秒两次请求
    jmeter压力测试的简单实例+badboy脚本录制
    JMeter问题集
    英语自然拼读法基本规则和小窍门
    Jmeter工具做性能测试 常见的错误汇总
    如何使用JDK自带工具JConsole
    第七章 JMeter 逻辑控制器
    第六篇:JMeter 断言
  • 原文地址:https://www.cnblogs.com/wsyunine/p/14733041.html
Copyright © 2011-2022 走看看