Codeforces Round #290 (Div. 1) C. Fox And Dinner 奇偶建图跑最大流

Codeforces Round #290 Div. 1 C. Fox And Dinner 奇偶建图跑最大流


传送门: https://codeforces.com/contest/512/problem/C

题意

有 n 个 数 , 问 能 不 能 把 n 个 数 分 成 k 桌 , 且 要 求 如 下 有n个数,问能不能把n个数分成k桌,且要求如下 nnk

  • 每 桌 至 少 3 个 数 以 上 每桌至少3个数以上 3
  • 一 桌 上 相 邻 的 数 相 加 为 素 数 一桌上相邻的数相加为素数

问 能 不 能 构 造 出 k 桌 , 能 则 输 出 , 否 则 输 出 − 1. 问能不能构造出k桌,能则输出,否则输出-1. k1.

思路

题 目 要 求 相 连 的 数 相 加 为 素 数 , 我 们 知 道 , 这 两 个 数 一 定 是 一 奇 一 偶 。 题目要求相连的数相加为素数,我们知道,这两个数一定是一奇一偶。
而 奇 数 相 邻 两 个 一 定 是 偶 数 , 偶 数 相 邻 两 个 一 定 是 奇 数 。 所 以 可 以 建 立 网 络 流 模 型 。 而奇数相邻两个一定是偶数,偶数相邻两个一定是奇数。所以可以建立网络流模型。

先 判 断 两 个 数 相 加 是 否 为 素 数 , 是 的 话 就 将 奇 数 向 偶 数 连 一 条 有 向 边 , 并 且 容 量 为 1 。 先判断两个数相加是否为素数,是的话就将奇数向偶数连一条有向边,并且容量为1。 1
而 这 个 奇 数 可 以 连 接 两 个 偶 数 , 所 以 将 源 点 向 这 个 奇 数 连 接 一 条 有 向 边 , 容 量 为 2 。 而这个奇数可以连接两个偶数,所以将源点向这个奇数连接一条有向边,容量为2。 2
同 样 , 每 个 偶 数 都 要 向 汇 点 连 接 一 条 有 向 边 , 容 量 为 2 。 同样,每个偶数都要向汇点连接一条有向边,容量为2。 2

跑 一 遍 最 大 流 , 如 果 最 大 流 = n , 则 是 可 以 得 到 k 桌 。 在 残 留 网 络 上 跑 一 遍 D F S 即 可 。 跑一遍最大流,如果最大流=n,则是可以得到k桌。在残留网络上跑一遍DFS即可。 =nkDFS

注 意 : n 为 奇 数 一 定 是 不 存 在 。 注意:n为奇数一定是不存在。 n

Code(30MS)

#include "bits/stdc++.h"
 using namespace std;

#define INF 0x3f3f3f3f
 
const int N = 405, M = 10005;
int n, m, s, t;
int maxflow;
int deep[N], cur[N];
 
struct Edge {
    
    
    int v, next, cap;
}e[M << 1];
int head[M << 1], cnt;
 
void init() {
    
    
    mem(head, -1);
    cnt = maxflow = 0;
}
 
inline void add(int u, int v, int cap) {
    
    
    e[cnt].v = v;
    e[cnt].cap = cap;
    e[cnt].next = head[u];
    head[u] = cnt++;
 
    e[cnt].v = u;
    e[cnt].cap = 0;
    e[cnt].next = head[v];
    head[v] = cnt++;
}
 
bool bfs() {
    
    
    for(int i = 0;i <= t; i++) {
    
    
        deep[i] = -1; cur[i] = head[i];
    }
    queue<int> q;
    q.push(s); deep[s] = 0;
    while(!q.empty()) {
    
    
        int u = q.front(); q.pop();
        for(int i = head[u]; ~i; i = e[i].next) {
    
    
            int v = e[i].v;
            if(deep[v] == -1 && e[i].cap) {
    
    
                deep[v] = deep[u] + 1;
                q.push(v);
            }
        }
    }
    if(deep[t] >= 0) return true;
    else return false;
}
 
int dfs(int u, int mx) {
    
    
    int a;
    if(u == t) return mx;
    for(int i = cur[u]; ~i; i = e[i].next) {
    
    
        cur[u] = i;
        int v = e[i].v;
        if(e[i].cap && deep[v] == deep[u] + 1 && (a = dfs(v, min(mx, e[i].cap)))) {
    
    
            e[i].cap -= a;
            e[i ^ 1].cap += a;
            return a;
        }
    }
    return 0;
}
 
void dinic() {
    
    
    int res;
    while(bfs()) {
    
    
        while(1) {
    
    
            res = dfs(s, INF);
            if(!res) break;
            maxflow += res;
        }
    }
}
 
const int maxn = 4e4 + 10;
bool is_prime[maxn];
void sieve() {
    
    
    for(int i = 2;i < maxn; i++) {
    
    
        if(!is_prime[i]) {
    
    
            for(int j = i + i;j < maxn; j += i) {
    
    
                is_prime[j] = true;
            }
        }
    }
}
 
vector<int> ans[N];
bool vis[N];
int ver;
 
void DFS(int u) {
    
    
    vis[u] = 1;
    ans[ver].push_back(u); int v;
    for(int i = head[u]; ~i; i = e[i].next) {
    
    
        if(e[i].cap) continue;
        v = e[i].v;
        if(vis[v]) continue;
        vis[v] = 1;
        ans[ver].push_back(v);
        break;
    }
    for(int i = head[v]; ~i; i = e[i].next) {
    
    
        if(e[i ^ 1].cap) continue;
        v = e[i].v;
        if(vis[v]) continue;
        vis[v] = 1;
        DFS(v);
    }
}
 
vector<int> a(405);
 
void solve() {
    
    
    sieve();
    init();
    cin >> n;
    if(n & 1) {
    
    
        cout << "Impossible" << endl;
        return ;
    }
    s = 0; t = n + 1;
    for(int i = 1;i <= n; i++) {
    
    
        cin >> a[i];
        if(a[i] & 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(!is_prime[a[i] + a[j]]) {
    
    
                if(a[i] & 1)
                    add(i, j, 1); // 奇数连接偶数
            }
        }
    }
    dinic();
    if(maxflow != n) {
    
    
        cout << "Impossible" << endl;
        return ;
    }
    for(int i = 1;i <= n; i++) {
    
    
        if(!vis[i] && (a[i] & 1)) {
    
    
            DFS(i); // 搜索每一桌
            ver++;
        }
    }
    cout << ver << endl;
    for(int i = 0;i < ver; i++) {
    
    
        cout << ans[i].size();
        for(int j = 0;j < ans[i].size(); j++) {
    
    
            cout << " " << ans[i][j];
        }
        cout << endl;
    }
}
 
signed main() {
    
    
    solve();
}

猜你喜欢

转载自blog.csdn.net/fztsilly/article/details/113703312