Bitset 练习

Bipartite Graph

 (HDU - 5313 

若干个二分图两侧的点数是定值,现在就是要选择翻转一些二分图,再拼起来,最后使得两边的点数尽量接近,这样可以达到最大。

考虑背包DP,dp[i]表示i这个值是否凑的出来,有:

if(dp[i]) dp[i+w[now]]=1

那么就很套路地使用Bitset优化,每次只要或一下左移后的结果就行了。

CODE:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <bitset>
#include <vector>
using namespace std;
const int maxn=1e4+10;
const int maxm=1e5+10;
struct point
{
    int to;
    int nxt;
}edge[maxm*2];
struct nod
{
    int a,b;
    nod(int a,int b):a(a),b(b) {};  
};
int n,m,T,na,nb,tot;
vector<nod> ans;
int vis[maxn],head[maxn];

inline void add(int u,int v)
{
    tot++;
    edge[tot].nxt=head[u];
    edge[tot].to=v;
    head[u]=tot;
}

inline void dfs(int x,int ff)
{
    if(ff) na++;
    else nb++;
    vis[x]=1;
    for(int i=head[x];i;i=edge[i].nxt)
    {
        int v=edge[i].to;
        if(vis[v]) continue;
        dfs(v,ff^1);
    }
}

int main()
{
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&n,&m);
        tot=0;
        memset(vis,0,sizeof(vis));
        memset(head,0,sizeof(head));
        for(int i=1;i<=m;i++)
        {
            int u,v;
            scanf("%d%d",&u,&v);
            add(u,v),add(v,u);
        }
        ans.clear();
        for(int i=1;i<=n;i++)
        if(!vis[i])
        {
            na=nb=0;
            dfs(i,0);
            ans.push_back(nod(na,nb)); 
        }
        bitset<maxn> aa; 
        aa.set(0);
        int mm=ans.size();
        for(int i=0;i<mm;i++)
            aa=(aa<<ans[i].a)|(aa<<ans[i].b);
        int Max=0;
        for(int i=1;i<=n;i++)
            if(aa[i])
                Max=max(Max,i*(n-i)-m);
        printf("%d\n",Max);
    }
    return 0;
}
View Code

连通数

 HYSBZ - 2208 

很明显的Floyd传递闭包,但是会TLE,开n个Bitset f[i] 表示i可以到达的点集,每次传递的时候只要或一下就行了,注意循环的顺序。

每次把所有的点都要更新一遍,改成三重循环看一下就知道了。

CODE:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <bitset>
using namespace std;
const int maxn=2003;
bitset<maxn> f[maxn];
int n;
char ss[maxn];

int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%s",ss+1);
        for(int j=1;j<=n;j++)
            if(ss[j]-'0' || i==j) f[i][j]=1;
    }
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            if(f[j][i]) f[j]|=f[i];
    int ans=0;
    for(int i=1;i<=n;i++)
        ans+=f[i].count();
    printf("%d",ans);
    return 0;
}
View Code

猜你喜欢

转载自www.cnblogs.com/linda-fcj/p/9115978.html