zoukankan      html  css  js  c++  java
  • 【网络流24题】魔术球问题

    P1226 - 【网络流24题】魔术球问题

    Description

    假设有n根柱子,现要按下述规则在这n根柱子中依次放入编号为 1,2,3,4......的球。
    (1)每次只能在某根柱子的最上面放球。
    (2)在同一根柱子中,任何2个相邻球的编号之和为完全平方数。
    试设计一个算法,计算出在n根柱子上最多能放多少个球。例如,在4 根柱子上最多可 放11个球。
    ´编程任务:
    对于给定的n,计算在 n根柱子上最多能放多少个球。

    Input

    第1 行有 1个正整数n,表示柱子数。

    Output

    第一行是球数。

    Sample Input

    4

    Sample Output

    11

    问题转化为最小路径覆盖的逆问题,从1开始枚举答案,跑最大流,计算出最小覆盖。
    当最小覆盖>n时退出。
    这里的实现有一个技巧:
    在每次枚举时并不需要重新连边,只需要加上这次枚举的答案所连的边,然后在上次的残余网络上跑最大流就可以了。
     1 #include<set>
     2 #include<map>
     3 #include<queue>
     4 #include<stack>
     5 #include<ctime>
     6 #include<cmath>
     7 #include<string>
     8 #include<vector>
     9 #include<cstdio>
    10 #include<cstdlib>
    11 #include<cstring>
    12 #include<iostream>
    13 #include<algorithm>
    14 using namespace std;
    15 struct data{
    16   int nex,to,w;
    17 }e[700000];
    18 int head[10100],edge=-1,lev[10100];
    19 void add(int from,int to,int w){
    20   e[++edge].nex=head[from];
    21   e[edge].to=to;
    22   e[edge].w=w;
    23   head[from]=edge;
    24 }
    25 inline bool bfs(int s,int t){
    26   queue<int>q;
    27   memset(lev,0,sizeof(lev));
    28   lev[s]=1;
    29   q.push(s);
    30   while(!q.empty()){
    31     int u=q.front();
    32     q.pop();
    33     for(int i=head[u];i!=-1;i=e[i].nex)
    34       if(!lev[e[i].to] && e[i].w>0){
    35     lev[e[i].to]=lev[u]+1;
    36     if(e[i].to==t) return 1;
    37     else q.push(e[i].to);
    38       }
    39   }
    40   return 0;
    41 }
    42 int dfs(int s,int t,int k){
    43   if(s==t) return k;
    44   int rag=0;
    45   for(int i=head[s];i!=-1;i=e[i].nex)
    46     if(e[i].w>0 && lev[e[i].to]==lev[s]+1){
    47       int d=dfs(e[i].to,t,min(k-rag,e[i].w));
    48       e[i].w-=d;
    49       e[i^1].w+=d;
    50       rag+=d;
    51       if(rag==k) return rag;
    52     }
    53   return rag;
    54 }
    55 int dinic(int s,int t){
    56   int flow=0;
    57   while(bfs(s,t))flow+=dfs(s,t,1999999999);
    58   return flow;
    59 }
    60 int main()
    61 {
    62   freopen("!.in","r",stdin);
    63   freopen("!.out","w",stdout);
    64   int n;scanf("%d",&n);
    65   memset(head,-1,sizeof(head));
    66   int num=0,ans=0,s=0,t=10010;
    67   while(1){
    68     num++,ans++;
    69     for(int i=1;i<num;i++)
    70       if(sqrt(i+num)==(int)(sqrt(i+num))) add(i,num+2000,1),add(num+2000,i,0);
    71     add(s,num,1),add(num,s,0);add(num+2000,t,1),add(t,num+2000,0);
    72     ans-=dinic(s,t);
    73     if(ans>n) break;
    74   }
    75   printf("%d",num-1);
    76   return 0;
    77 }
    
    
    
     
  • 相关阅读:
    12个Web开发者应该掌握的Firebug技巧
    sql语句修改表结构
    从数据库中查询数据
    收发短信API
    日志12.03
    监听短信数据库变化
    漫谈C语言及如何学习C语言(转)
    阅读短信
    在src文件中寻找短信数据库表
    拦截短信示例1
  • 原文地址:https://www.cnblogs.com/pantakill/p/6613485.html
Copyright © 2011-2022 走看看