NOIPTGA组T2 高维宇宙

本文介绍了一种基于素数匹配的算法问题解决方法。通过构建图模型并利用最大匹配算法来找出序列中两数之和为素数的所有匹配对。文章详细解释了如何通过边连接可能的匹配对,并运用深度优先搜索进行遍历找到所有有效匹配。

题意:给你一个序列,假设其中有两个数相加为素数,叫做一个匹配。求有多少个匹配。
一开始就想歪了(别想多),往DP想,结果真被我推出来了。。
一开始以为是设dp[i,j]表示i到j有多少个匹配,然而最后发现错了。。
正解是吧任意两个为匹配的数连边,做最大匹配。。(其实超级显然就是我一开始想歪了。。。。)
顺便复习一波最大匹配。。。

r
        head,go,next:Array[0..100000]of longint;
        vis,pd,jud,data,bo,a:Array[0..1000]of longint;
        i,j,k,n,m,tot,ans:longint;
function prm(x:longint):boolean;
var
        i:longint;
begin
        if x=1 then exit(false);
        for i:=2 to trunc(sqrt(x)) do
        if x mod i=0 then exit(false);
        exit(true);
end;
procedure add(x,y:longint);
begin
        inc(tot);
        go[tot]:=y;
        next[tot]:=head[x];
        head[x]:=tot;
end;
procedure dfs(x:longint);
var
        i,v:longint;
begin
        i:=head[x];
        while i<>0 do
        begin
                v:=go[i];
                if 0=vis[v] then
                begin
                        vis[v]:=1;
                        if pd[x]=0 then pd[v]:=1
                        else pd[v]:=0;
                        dfs(v);
                        if (pd[v]<>pd[x]) and(jud[x]=0)and(jud[v]=0)then
                        begin
                                inc(ans);
                                jud[x]:=1;
                                jud[v]:=1;
                        end;
                end;
                i:=next[i];
        end;
end;
begin
        assign(input,'prime.in');
        assign(output,'prime.out');
        reset(input);
        rewrite(output);
        readln(n);
        for i:=1 to n do
        read(a[i]);
        for i:=1 to n do
        for j:=i+1 to n do
        begin
                if prm(a[i]+a[j])then
                begin
                        add(i,j);
                        add(j,i);
                        bo[i]:=1;
                        bo[j]:=1;
                end;
        end;
        for i:=0 to 1000 do pd[i]:=-1;
        for i:=1 to n do
        if (bo[i]<>0)and(pd[i]=-1) then
        begin
                pd[i]:=0;
                dfs(i);
        end;
        writeln(ans);
end.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值