Codeforces Round #290 (Div. 2) E. Fox And Dinner

题目描述:戳这里

题解:

这题是一道比较猥琐的网络流题。
我们注意到一个质数(>2)肯定是由一个偶数和一个奇数相加得到的。那么我们就可以将奇数和偶数连边,然后跑一趟二分图匹配。但是考虑到每一桌至少要有三个人,而匈牙利算法是无法解决这一条件的,那么就要用网络流来解决。
注意到一个奇数肯定与两个偶数相邻这个条件,那么我们就可以从奇数的节点向偶数的节点连边,流量为1,然后从源点S向奇数点连边,偶数点向T连边,流量均为2,这样就能保证前面的条件。
接下来就只要刷一下DINIC就好了。
如果有答案,就dfs一下,刷出每一组的答案。

代码如下:

#include<bits/stdc++.h>
using namespace std;
const int maxn=210,maxm=40010,inf=1e8;
int n,S,T,m,tot,a[maxn],lnk[maxn],son[maxm],nxt[maxm],que[maxn],w[maxm],dep[maxn],cur[maxn],fa[maxn],ans[maxn][maxn];
bool check(int x){
    int sq=sqrt(x);
    for (int i=2;i<=sq;i++) if (x%i==0) return 0;
    return 1;
}
void add(int x,int y,int z){
    son[++tot]=y,w[tot]=z,nxt[tot]=lnk[x],lnk[x]=tot;
    son[++tot]=x,w[tot]=0,nxt[tot]=lnk[y],lnk[y]=tot;
}
bool bfs(){
    int head=0,tail=1; que[tail]=S;
    memset(dep,255,sizeof(dep)); dep[S]=0;
    while (head<tail){
        head++;
        for (int j=lnk[que[head]];j!=-1;j=nxt[j])
        if (dep[son[j]]==-1&&w[j]>0) {
            dep[son[j]]=dep[que[head]]+1; que[++tail]=son[j];
        }
    }
    if (dep[T]==-1) return 0; else return 1;
}
int dfs(int x,int flow){
    if (x==T) return flow;
    for (int& j=cur[x];j!=-1;j=nxt[j])
    if (dep[son[j]]==dep[x]+1&&w[j]!=0){
        int x=dfs(son[j],min(flow,w[j]));
        if (x) {w[j]-=x; w[j^1]+=x; return x;}
    }
    return 0;
}
int dinic(){
    int ans=0;
    while (bfs()){
        for (int i=1;i<=T;i++) cur[i]=lnk[i];
        int sum; while (sum=dfs(S,inf)) ans+=sum;
    }
    return ans;
}
void find(int x,int sum){
    fa[x]=sum; ans[sum][++ans[sum][0]]=x;
    if (a[x]%2==1) {
        for (int j=lnk[x];j!=-1;j=nxt[j])
        if (w[j]==0&&!fa[son[j]]) find(son[j],sum);
    } else {
        for (int j=lnk[x];j!=-1;j=nxt[j])
        if (w[j^1]==0&&!fa[son[j]]) find(son[j],sum);
    }
}
int main(){
    tot=-1; memset(lnk,255,sizeof(lnk)); memset(nxt,255,sizeof(nxt));
    scanf("%d",&n);
    for (int i=1;i<=n;i++) scanf("%d",&a[i]);
    T=n+2,S=n+1;
    for (int i=1;i<=n;i++) if (a[i]%2==1) add(S,i,2); else add(i,T,2);
    for (int i=1;i<=n;i++)
    for (int j=1;j<=n;j++)
    if (a[i]%2==1&&a[j]%2==0&&check(a[j]+a[i])) add(i,j,1);
    int flo=dinic();
    if (flo!=n) {printf("Impossible\n"); return 0;}
    int s=0;
    for (int i=1;i<=n;i++) if (!fa[i]) find(i,++s);
    printf("%d\n",s);
    for (int i=1;i<=s;i++) {
        printf("%d ",ans[i][0]);
        for (int j=1;j<=ans[i][0];j++) printf("%d ",ans[i][j]);
        printf("\n");
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值