【NOIP2016提高A组集训第3场10.31】高维宇宙

本文介绍了解决特定类型的最大流问题的方法。通过将奇数和偶数分别放置在图的两侧,并依据特定条件建立连接,利用Dinic算法求解最大流问题。文章详细展示了算法实现过程及代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Description
这里写图片描述
Input
这里写图片描述
Sample Input

5
2 9 11 12 37
Output
这里写图片描述
Sample Output

2
这里写图片描述
Data Constraint
这里写图片描述

题解

首先我们发现如果有一对解(a,b)是合法的,那么a,b一定是一个奇数一个偶数(否则加起来就是一个偶数了,而且题目中的范围ai<=2,所以和不可能等于2)
那么我们把所有的奇数放到左边,把所有的偶数放到右边,如果有(x,y)是合法的,那么就从x连一条流量为1的边
源点到每一个奇数所在的点都连一条流量为1的边
每一个偶数所在的点都朝汇点连一条流量为1的边
那么就跑一个最大流就好了
我打的是dinic

贴代码

var
    map:array[0..45,0..45]of longint;
    deep:array[0..45]of longint;
    su:array[0..20005]of boolean;
    a,b:array[0..45]of longint;
    i,j,k,l,n,x,m,ans:longint;
function min(x,y:longint):longint;
begin
    if x>y then exit(y) else exit(x);
end;
function bfs:boolean;
var
    i,j,k:longint;
    h:array[0..55]of longint;
begin
    fillchar(deep,sizeof(deep),128);
    h[1]:=1;
    i:=1;
    j:=0;
    deep[1]:=0;
    while i>j do
    begin
        inc(j);
        for k:=1 to m do
        if (map[h[j],k]>0) and (deep[k]<0) then
        begin
            deep[k]:=deep[h[j]]+1;
            inc(i);
            h[i]:=k;
        end;
    end;
    if deep[m]>0 then exit(true) else exit(false);
end;
function dinic(x,low:longint):longint;
var
    i,p:longint;
begin
    p:=0;
    if x=m then exit(low);
    for i:=1 to m do
    if (map[x,i]>0) and (deep[i]=deep[x]+1) then
    begin
        p:=dinic(i,min(low,map[x,i]));
        if p>0 then
        begin
            map[x,i]:=map[x,i]-p;
            map[i,x]:=map[i,x]+p;
            exit(p);
        end;
    end;
    exit(0);
end;
procedure make_su;
var
    i,j:longint;
begin
    fillchar(su,sizeof(su),true);
    for i:=2 to 2000 do
    if su[i]=true then
    begin
        j:=i+i;
        while j<=2000 do
        begin
            su[j]:=false;
            j:=j+i;
        end;
    end;
end;
begin
    assign(input,'prime.in'); reset(input);
    assign(output,'prime.out'); rewrite(output);
    readln(n);
    for i:=1 to n do
    begin
        read(x);
        if x mod 2=1 then
        begin
            inc(k);    
            a[k]:=x;
        end
        else
        begin
            inc(l);
            b[l]:=x;
        end;
    end;
    make_su;
    for i:=1 to k do
        for j:=1 to l do
        if su[a[i]+b[j]]=true then map[i+1,k+j+1]:=1;
    for i:=1 to k do map[1,i+1]:=1;
    m:=k+l+2;
    for i:=k+2 to k+l+1 do map[i,m]:=1;
    while bfs do
    begin
        repeat
            l:=dinic(1,maxlongint div 3);
            ans:=ans+l;
        until l=0;
    end;
    writeln(ans);
    close(input); close(output);
end.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值