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

刚看到这道题的时候就有感觉是一个图论题。。因为可以通过和为质数的两个数字之间建边来构图,但是怎么判成环一直在纠结,最后还是没纠结出来,就去看题解了ORZ

然后看到了奇偶建图。。瞬间开窍。。因为感觉质数环肯定是奇偶交替的数形成的,对于两个和为质数的数a,b 。a为偶数,b为奇数,源点为s,汇点为t,只需要建立如下边

s->a   容量为2

a->b   容量为1

b->t    容量为2

只要能够达到满流那么就说明有解,否则无解,因为要达到满流必须要满足每个奇数都和两个偶数相连,每个偶数都和两个奇数相连。


之后怎么把质数环搞出来呢,我用的是一个比较暴力的方法:

在残余网络中:

(1)对于一个偶数节点就搜一条容量为0的边(正边)到达一个奇数节点

(1)对于一个奇数节点就搜一条容量为1的边(反向边)到达一个偶数节点

重复(1),(2)直到搜到一个环

具体看代码吧。。。调试了好久好久。。写得比较挫。

#include<iostream>
#include<sstream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<stack>
#include<math.h>
#include<map>
#include<time.h>
#include<set>
#include<string>
#include<vector>
#include<algorithm>
using namespace std;
#define inf 0x7fffffff
#define lc l,m,index<<1
#define rc m+1,r,index<<1|1
#define max_n 200005
#define mod 10000007
#define LL  __int64
struct edge
{
    int to,cap,rev;
};
vector<edge> G[max_n];
bool used[max_n];
int num[max_n];
int id[max_n];
int n;
void add_edge(int from,int to,int cap)
{
    G[from].push_back((edge){to,cap,G[to].size()});
    G[to].push_back((edge){from,0,G[from].size()-1});
}
int dfs(int v,int t,int f)
{
   // printf("%d ",v);
    if(v==t) return f;
    used[v] = true;

    for(int i=0;i<G[v].size();i++)
    {
        edge &e=G[v][i];
        if(!used[e.to] && e.cap>0)
        {
            int d=dfs(e.to,t,min(f,e.cap));
            if(d>0)
            {
                e.cap-=d;
                G[e.to][e.rev].cap+=d;
                return d;
            }
        }
    }
    return 0;
}
int max_flow(int s,int t)
{
    int flow=0;
    while(1)
    {
        memset(used,0,sizeof(used));
        int f=dfs(s,t,inf);
       // printf("\n");
       // printf("f == %d\n",f);
       // system("pause");
        if(f==0) return flow;
        flow+=f;
    }

}
bool judge(int x)
{
    for(int i=2;i<=(int)sqrt(x);i++)
    {
        if(x%i==0) return 0;
    }
    return 1;
}
bool judge1(bool a[])
{
    for(int i=1;i<=n;i++)
    {
        if(!used[i])return 0;
    }
    return 1;
}
void Dfs(int v,vector<int> &ans)
{
    ans.push_back(v);
    used[v]=1;
    int l;
    if(num[v-1]%2==0)
    l=0;
    else
    l=1;
    for(int i=0;i<G[v].size();i++)
    {
        edge e=G[v][i];
        if(!used[e.to] && e.cap==l && e.to!=0 && e.to!=10005)
            Dfs(e.to,ans);
    }
}
void solve()
{
    int res=max_flow(0,10005);
    if(res!=n)
    {
       // printf("%d\n",res);
        printf("Impossible\n");
        return ;
    }

    vector<int>ans[10005];
    int index=0;

    memset(used,0,sizeof(used));

    while(!judge1(used))
    {
        for(int i=0;i<n;i++)
        {
            if(!used[i+1])
            {
                Dfs(i+1,ans[index++]);
            }
        }
    }
    printf("%d\n",index);
    for(int i=0;i<index;i++)
    {
        printf("%d",ans[i].size());
        for(int j=0;j<ans[i].size();j++)
        printf(" %d",ans[i][j]);
        printf("\n");
    }
}
int main()
{
    while(~scanf("%d",&n))
    {

        for(int i=0;i<n;i++)
            scanf("%d",&num[i]);

        memset(used,0,sizeof(used));

        for(int i=0;i<n;i++)
        {
            for(int j=i+1;j<n;j++)
            {
                if(judge(num[i]+num[j]))
                {
                    int s=i+1;
                    int t=j+1;
                    if(num[i]%2==0 && num[j]%2!=0)
                    {

                       // printf("0-->%d-->%d-->10005\n",num[i],num[j]);
                        add_edge(s,t,1);
                        if(!used[s])
                        {
                            add_edge(0,s,2);
                            used[s]=1;
                        }
                       // printf("0-->%d\n",num[i]);
                        if(!used[t])
                        {
                            add_edge(t,10005,2);
                            used[t]=1;
                        }
                    }
                    else if(num[j]%2==0 && num[i]%2!=0)
                    {
                       // printf("0-->%d-->%d-->10005\n",num[j],num[i]);
                        add_edge(t,s,1);
                        if(!used[t])
                        {
                            add_edge(0,t,2);
                            used[t]=1;
                        }
                        if(!used[s])
                        {
                            add_edge(s,10005,2);
                            used[s]=1;
                        }
                    }
                }
            }
        }
        /*
        for(int i=0;i<n;i++)
        {
            int s=num[i];
            for(int j=0;j<G[s].size();j++)
            printf("%d-->%d %d\n",s,G[s][j].to,G[s][j].cap);
        }*/
        solve();
    }
    return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值