• AtCoder Beginner Contest 263 G.Erasing Prime Pairs(二分图最大匹配-网络流)


    题目

    黑板上有n(n<=100)个不同的数,第i个数ai(1<=ai<=1e7)出现了bi(1<=1e9)次,

    你每次可以选择当前黑板上存在的两个数x、y,满足x+y是质数,擦掉这两个数,

    求可以擦掉的最大次数

    思路来源

    AtCoder Beginner Contest 题目选解 - 云浅知处 - 博客园

    题解

    先考虑a,b,c互不相同的情形,三个素数里面必有至少两个数是奇素数,

    不妨a+b和a+c是奇数,则b和c同奇偶,b+c之和必为偶数,b不等于c则b+c不等于2,

    所以b+c不为素数,原图是一个近似二分图的图,

    但是,注意到b=c=1的时候,例如a=4,b=c=1,两两匹配也均为素数

    自己wa的过程和思路来源基本一模一样,所以直接粘过来了…

    考虑原图除了1以外,其余部分都是二分图,1和1自己能构成素数2,有一个自环

    所以考虑把1拆成2个点,入点和出点,再连边,答案就对了

    无向图最大匹配拆入点和出点,答案需要除以2这个也是典中典了…

    代码

    1. #include
    2. using namespace std;
    3. typedef long long ll;
    4. const int INF=0x3f3f3f3f;
    5. const int maxn=210,N=maxn;
    6. const int maxm=maxn*maxn*5+10,M=2e7+10;
    7. int level[maxn];
    8. int head[maxn],cnt;
    9. int t,n,m,a[N],b[N],col[N],to[N];
    10. int ss,ee;
    11. bool ok[M];
    12. int prime[M],tot;
    13. struct edge{int v,nex;ll w;}e[maxm];
    14. void init()
    15. {
    16. cnt=0;
    17. memset(head,-1,sizeof head);
    18. }
    19. void add(int u,int v,ll w)
    20. {
    21. e[cnt].v=v;
    22. e[cnt].w=w;
    23. e[cnt].nex=head[u];
    24. head[u]=cnt++;
    25. }
    26. void add2(int u,int v,ll w,bool op)//是否为有向图
    27. {
    28. add(u,v,w);
    29. add(v,u,op?0:w);
    30. }
    31. bool bfs(int s,int t)
    32. {
    33. queue<int>q;
    34. memset(level,0,sizeof level);
    35. level[s]=1;
    36. q.push(s);
    37. while(!q.empty())
    38. {
    39. int x=q.front();
    40. q.pop();
    41. if(x==t)return 1;
    42. for(int u=head[x];~u;u=e[u].nex)
    43. {
    44. int v=e[u].v;ll w=e[u].w;
    45. if(!level[v]&&w)
    46. {
    47. level[v]=level[x]+1;
    48. q.push(v);
    49. }
    50. }
    51. }
    52. return 0;
    53. }
    54. ll dfs(int u,ll maxf,int t)
    55. {
    56. if(u==t)return maxf;
    57. ll ret=0;
    58. for(int i=head[u];~i;i=e[i].nex)
    59. {
    60. int v=e[i].v;ll w=e[i].w;
    61. if(level[u]+1==level[v]&&w)
    62. {
    63. ll MIN=min(maxf-ret,w);
    64. w=dfs(v,MIN,t);
    65. e[i].w-=w;
    66. e[i^1].w+=w;
    67. ret+=w;
    68. if(ret==maxf)break;
    69. }
    70. }
    71. if(!ret)level[u]=-1;//优化,防止重搜,说明u这一路不可能有流量了
    72. return ret;
    73. }
    74. ll Dinic(int s,int t)
    75. {
    76. ll ans=0;
    77. while(bfs(s,t))
    78. ans+=dfs(s,INF,t);
    79. return ans;
    80. }
    81. void sieve()
    82. {
    83. for(ll i=2;i
    84. {
    85. if(!ok[i])prime[tot++]=i;
    86. for(int j=0;j
    87. {
    88. if(i*prime[j]>=M)break;
    89. ok[i*prime[j]]=1;
    90. if(i%prime[j]==0)break;
    91. }
    92. }
    93. }
    94. int main(){
    95. init();
    96. sieve();
    97. scanf("%d",&n);
    98. for(int i=1;i<=n;++i){
    99. scanf("%d%d",&a[i],&b[i]);
    100. }
    101. ss=2*n+1;ee=2*n+2;
    102. for(int i=1;i<=n;++i){
    103. add2(ss,i,b[i],1);
    104. add2(i+n,ee,b[i],1);
    105. for(int j=1;j<=n;++j){
    106. if(!ok[a[i]+a[j]]){
    107. add2(i,j+n,min(b[i],b[j]),1);
    108. add2(j,i+n,min(b[i],b[j]),1);
    109. }
    110. }
    111. }
    112. ll ans=Dinic(ss,ee);
    113. printf("%lld\n",ans/2);
    114. return 0;
    115. }
    116. //1 6 7 12

  • 相关阅读:
    Web服务器实战
    【Java】字节流、字符流、IO异常、属性集
    线程和进程
    汽车社媒营销创新玩法,品牌“自爆”不走寻常路
    Python教程之字典(Dictionary)操作详解
    ShardingSphere入门
    新手入门MyBatis的问题及如何解决?
    11、云服务器的宝塔面板安装、在宝塔安装MySQL、Redis、NGINX、JAVA
    信息系统项目管理师第四版学习笔记——项目成本管理
    开发者,为什么说容器技术的成熟预示着云原生时代的到来?
  • 原文地址:https://blog.csdn.net/Code92007/article/details/128063740