cf 510E Fox And Dinner 网络流

题意:每个狐狸都有一个编号,问是否可以将狐狸分成几个桌子,使得相邻的狐狸的编号和为素数,每个桌子至少有三个。

只有相邻两个狐狸一奇一偶才有可能为素数,且每一个狐狸度数为2,所以建立一个二分图,一边为偶,一边为奇,源点到偶度数容量为2,奇数到汇点容量为2,一个偶数加一个奇数为素数,则连接这两点,跑最大流,若流量为n则可以,否则不可能。

<span style="font-size:14px;">#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
using namespace std;
#define maxn 500
#define INF 10000000
struct Edge
{
    int from, to, cap, flow;
}edges[360000];

int n, s, t, cnt;
int isp[20100],a[300],tot;
vector<int> G[maxn],vv[300],odd,even;   // 邻接表,G[i][j]表示结点i的第j条边在e数组中的序号
bool vis[maxn];        // BFS使用
int d[maxn];           // 从起点到i的距离
int cur[maxn];         // 当前弧指针
void AddEdge(int from, int to, int cap)
{
    edges[cnt].from=from;
    edges[cnt].to=to;
    edges[cnt].cap=cap;
    edges[cnt].flow=0;
    G[from].push_back(cnt);
    cnt++;
    edges[cnt].from=to;
    edges[cnt].to=from;
    edges[cnt].cap=0;
    edges[cnt].flow=0;
    G[to].push_back(cnt);
    cnt++;
}
bool BFS()
{
    memset(vis, 0, sizeof(vis));
    queue<int> Q;
    Q.push(s);
    vis[s] = 1;
    d[s] = 0;
    while(!Q.empty())
    {
        int x = Q.front(); Q.pop();
        for(int i = 0; i < G[x].size(); i++)
        {
            Edge& e = edges[G[x][i]];
            if(!vis[e.to] && e.cap > e.flow)
            {
                vis[e.to] = 1;
                d[e.to] = d[x] + 1;
                Q.push(e.to);
            }
        }
    }
    return vis[t];
}
int DFS(int x, int a)
{
    if(x == t || a == 0) return a;
    int flow = 0, f;
    for(int& i = cur[x]; i < G[x].size(); i++)
    {
        Edge& e = edges[G[x][i]];
        if(d[x] + 1 == d[e.to] && (f = DFS(e.to, min(a, e.cap-e.flow))) > 0)
        {
            e.flow += f;
            edges[G[x][i]^1].flow -= f;
            flow += f;
            a -= f;
            if(a == 0) break;
        }
    }
    if(flow==0) d[x]=-1;
    return flow;
}
void dfs(int u)
{
    vv[tot].push_back(u);
    vis[u]=1;
    for(int i=0;i<G[u].size();i++)
    {
        Edge e = edges[G[u][i]];
        if(e.to!=s&&e.to!=t&&!vis[e.to]&&abs(e.flow)==1) dfs(e.to);
    }
}
int Maxflow()
{
    int flow = 0;
    while(BFS())
    {
        memset(cur, 0, sizeof(cur));
        flow += DFS(s, INF);
    }
    return flow;
}
int main()
{
    int m=sqrt(20000+10);
    memset(isp,0,sizeof(isp));
    for(int i=2;i<=m;i++)
        if(!isp[i])
            for(int j=i*i;j<=20010;j+=i)
                isp[j]=1;
    scanf("%d",&n);
    cnt=0;
    for(int i=0;i<=n+10;i++) { G[i].clear(); vv[i].clear(); }
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    odd.clear(); even.clear();
    for(int i=1;i<=n;i++)
    {
        if(a[i]%2==0)
        {
            AddEdge(0,i,2);
            even.push_back(i);
        }
        if(a[i]%2==1)
        {
            AddEdge(i,n+1,2);
            odd.push_back(i);
        }
    }
    if(odd.size()!=even.size()) { printf("Impossible\n"); return 0; }
    for(int i=0;i<even.size();i++)
        for(int j=0;j<odd.size();j++)
            if(!isp[ a[even[i]]+a[odd[j]] ])
                AddEdge(even[i],odd[j],1);
    s=0;t=n+1;
    int flow=Maxflow();
    //printf("%d\n",flow);
    if(flow==n)
    {
        tot=0;
        memset(vis,0,sizeof(vis));
        for(int i=1;i<=n;i++)
            if(!vis[i]) { dfs(i); tot++; }
        printf("%d\n",tot);
        for(int i=0;i<tot;i++)
        {
            printf("%d",vv[i].size());
            for(int j=0;j<vv[i].size();j++) printf(" %d",vv[i][j]);
            printf("\n");
        }
    }
    else printf("Impossible\n");
    return 0;
}</span>


你可能感兴趣的:(cf 510E Fox And Dinner 网络流)