BZOJ4240: 有趣的家庭菜园
BZOJ2660: [Beijing wc2012]最多的方案

BZOJ4205: 卡牌配对

shinbokuow posted @ Aug 18, 2015 08:39:03 PM in BZOJ with tags 网络流 数学 , 1504 阅读

题解:

首先暴力连边匹配肯定是不行的...

由于$200$以内的质数仅有$46$个,我们构造三类点$ab(p_1,p_2),ac(p_1,p_2),bc(p_1,p_2)$分别表示参数1能被$p_1$整除,参数2能被$p_2$整除,剩下的依此类推.

然后对于左侧的点向符合条件的中间点连边.

对于右侧的点从符合条件的中间点连边.

这样做事实上是边分组,很显然是正确的.

直接用dinic玩就行了.

代码:

#include<cstdio>
#include<cctype>
#include<cstring>
#include<climits>
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
 
#define inf 0x3f3f3f3f
 
struct Solver{
    static const int V=100010;
    static const int E=3000010;
    int head[V],next[E],flow[E],end[E],ind,d[V];
    inline void reset(){
        memset(head,-1,sizeof head);
        ind=0;
    }
    inline void addedge(int a,int b,int f){
        int q=ind++;
        end[q]=b;
        next[q]=head[a];
        head[a]=q;
        flow[q]=f;
    }
    inline void make(int a,int b,int f){
        addedge(a,b,f);
        addedge(b,a,0);
    }
    inline bool bfs(int s,int t){
        static int q[V];
        int fr=0,ta=0;
        memset(d,-1,sizeof d);
        d[q[ta++]=s]=0;
        while(fr!=ta){
            int i=q[fr++];
            for(int j=head[i];j!=-1;j=next[j])
                if(flow[j]&&d[end[j]]==-1)
                    d[q[ta++]=end[j]]=d[i]+1;
        }
        return d[t]!=-1;
    }
    inline int dinic(int p,int t,int Maxflow){
        if(p==t)
            return Maxflow;
        int last=Maxflow;
        for(int j=head[p];j!=-1;j=next[j])
            if(flow[j]&&d[end[j]]==d[p]+1){
                int to=dinic(end[j],t,flow[j]>last?last:flow[j]);
                if(to){
                    flow[j]-=to;
                    flow[j^1]+=to;
                    if(!(last-=to))
                        return Maxflow;
                }
            }
        d[p]=-1;
        return Maxflow-last;
    }
    inline int Maxflow(int s,int t){
        int re=0;
        while(bfs(s,t))
            re+=dinic(s,t,inf);
        return re;
    }
}g;
 
#define N 210
int p[N],cnt;
bool np[N];
inline void pre(){
    int i,j;
    for(i=2;i<=200;++i){
        if(!np[i])
            p[++cnt]=i;
        for(j=1;j<=cnt&&p[j]*i<=200;++j){
            np[i*p[j]]=1;
            if(i%p[j]==0)
                break;
        }
    }
}
int a[51][51],b[51][51],c[51][51];
int x[2][30010],y[2][30010],z[2][30010];
 
vector<int>v[N];
int main(){
    pre();
    int n,m;
    cin>>n>>m;
    int i,j,k;
    for(i=1;i<=n;++i)
        scanf("%d%d%d",&x[0][i],&y[0][i],&z[0][i]);
    for(i=1;i<=m;++i)
        scanf("%d%d%d",&x[1][i],&y[1][i],&z[1][i]);
     
    for(i=1;i<=200;++i)
        for(j=1;j<=cnt;++j)
            if(i%p[j]==0)
                v[i].push_back(j);
     
    int id=n+m;
    for(i=1;i<=cnt;++i)
        for(j=1;j<=cnt;++j){
            a[i][j]=++id;
            b[i][j]=++id;
            c[i][j]=++id;
        }
     
    int s=0,t=++id;
     
    g.reset();
    for(i=1;i<=n;++i)
        g.make(s,i,1);
    for(i=1;i<=m;++i)
        g.make(n+i,t,1);
     
    int p,q;
    for(i=1;i<=n;++i){
        for(j=0;j<v[x[0][i]].size();++j)
            for(k=0;k<v[y[0][i]].size();++k){
                p=v[x[0][i]][j];
                q=v[y[0][i]][k];
                g.make(i,a[p][q],1);
            }
        for(j=0;j<v[x[0][i]].size();++j)
            for(k=0;k<v[z[0][i]].size();++k){
                p=v[x[0][i]][j];
                q=v[z[0][i]][k];
                g.make(i,b[p][q],1);
            }
        for(j=0;j<v[y[0][i]].size();++j)
            for(k=0;k<v[z[0][i]].size();++k){
                p=v[y[0][i]][j];
                q=v[z[0][i]][k];
                g.make(i,c[p][q],1);
            }
    }
    for(i=1;i<=m;++i){
        for(j=0;j<v[x[1][i]].size();++j)
            for(k=0;k<v[y[1][i]].size();++k){
                p=v[x[1][i]][j];
                q=v[y[1][i]][k];
                g.make(a[p][q],n+i,1);
            }
        for(j=0;j<v[x[1][i]].size();++j)
            for(k=0;k<v[z[1][i]].size();++k){
                p=v[x[1][i]][j];
                q=v[z[1][i]][k];
                g.make(b[p][q],n+i,1);
            }
        for(j=0;j<v[y[1][i]].size();++j)
            for(k=0;k<v[z[1][i]].size();++k){
                p=v[y[1][i]][j];
                q=v[z[1][i]][k];
                g.make(c[p][q],n+i,1);
            }
    }
     
    cout<<g.Maxflow(s,t)<<endl;
     
    return 0;
}

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter