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

    题目描述

    «问题描述:

    假设有n根柱子,现要按下述规则在这n根柱子中依次放入编号为1,2,3,...的球。

    (1)每次只能在某根柱子的最上面放球。

    (2)在同一根柱子中,任何2个相邻球的编号之和为完全平方数。

    试设计一个算法,计算出在n根柱子上最多能放多少个球。例如,在4 根柱子上最多可放11 个球。

    «编程任务:

    对于给定的n,计算在n根柱子上最多能放多少个球。

    输入输出格式

    输入格式:

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

    输出格式:

    程序运行结束时,将n 根柱子上最多能放的球数以及相应的放置方案输出。文件的第一行是球数。接下来的n行,每行是一根柱子上的球的编号。

    题解

    可以确定的是一定要边枚举当前要放的球边跑最大流

    两个加起来是完全平方的球之间一定是要连边的。

    由于放的顺序从小到大,所以连边的方向一定是从当前球向已放球

    边的容量均为1,每次在原网络上建边跑最大流,

    如果存在最大流,证明当前球可以放在另一球上面

    否则就要自立门户了。。。

    如果你单纯地按上面的描述建边,会发现出现了一点小问题。。。

    这时候需要用到一个小技巧————拆点

    将一个点拆成入点和出点,入点和s,出点和t连边,入点向出点连边

    完成!

      1 #include<cmath>
      2 #include<queue>
      3 #include<cstdio>
      4 #include<cstring>
      5 #include<algorithm>
      6 using namespace std;
      7 int n,m,cnt,tot,tp;
      8 int st,ed,ans,num;
      9 int head[200005];
     10 int cur[200005];
     11 int dis[200005];
     12 int pre[200005];
     13 bool usd[200005];
     14 int pr[200005];
     15 struct Edge{
     16     int fr;
     17     int to;
     18     int flw;
     19     int nxt;
     20 }edge[8888888];
     21 void init(){
     22     memset(head,-1,sizeof(head));
     23 }
     24 void addedge(int u,int v,int f){
     25     edge[cnt].fr=u;
     26     edge[cnt].to=v;
     27     edge[cnt].flw=f;
     28     edge[cnt].nxt=head[u];
     29     head[u]=cnt++;
     30     edge[cnt].fr=v;
     31     edge[cnt].to=u;
     32     edge[cnt].nxt=head[v];
     33     head[v]=cnt++;
     34 }
     35 int bfs(int ban){
     36     queue<int>que;
     37     memset(dis,0x3f,sizeof(dis));
     38     que.push(st);dis[st]=1;
     39     while(!que.empty()){
     40         int u=que.front();
     41         que.pop();
     42         for(int i=head[u];i!=-1;i=edge[i].nxt){
     43             int v=edge[i].to;
     44             if(ban==v)continue;
     45             if(!edge[i].flw)continue;
     46             if(dis[v]==0x3f3f3f3f){
     47                 dis[v]=dis[u]+1;
     48                 que.push(v);
     49             }
     50         }
     51     }
     52     return dis[ed]!=0x3f3f3f3f;
     53 }
     54 int dfs(int u,int flw){
     55     if(u==ed)return flw;
     56     int All=0,tmp;
     57     for(int i=cur[u];i!=-1;i=edge[i].nxt){
     58         if(!edge[i].flw)continue;
     59         int v=edge[i].to;cur[u]=i;
     60         if(dis[v]!=dis[u]+1)continue;
     61         if((tmp=dfs(v,min(flw,edge[i].flw)))>0){
     62             pre[v]=u;
     63             edge[i].flw-=tmp;
     64             edge[i^1].flw+=tmp;
     65             flw-=tmp,All+=tmp;
     66             if(!flw)break;
     67         }
     68     }
     69     return All;
     70 }
     71 int dinic(int ban){
     72     int ret=0;
     73     while(bfs(ban)){
     74         memcpy(cur,head,sizeof(cur));
     75         ret+=dfs(st,0x3f3f3f3f);
     76     }
     77     return ret;
     78 }
     79 int main(){
     80     init();ed=200000;
     81     scanf("%d",&n);
     82     while(true){
     83         ans++;
     84         addedge(st,ans*2-1,1);
     85         addedge(ans*2,ed,1);
     86         for(int i=1;i<ans;i++){
     87             int a=sqrt(ans+i);
     88               if(a*a!=ans+i)continue;
     89             addedge(i*2-1,ans*2,1);
     90         }
     91         num+=1-dinic(-1);
     92         if(num>n){
     93             printf("%d
    ",ans-1);
     94             dinic(ans*2);
     95             for(int i=1;i<ans;i++){
     96                 usd[(pre[2*i]+1)/2]=true;
     97             }
     98             for(int i=1;i<ans;i++){
     99                 if(!usd[i]){
    100                     int now=i;tp=0;
    101                     while(now){
    102                         pr[++tp]=now;
    103                         now=(pre[now*2]+1)/2;
    104                     }
    105                     for(int i=tp;i>=1;i--){
    106                         printf("%d",pr[i]);
    107                         if(i!=1)printf(" ");
    108                     }
    109                     printf("
    ");
    110                 }
    111             }
    112             break;
    113         }
    114     }
    115     return 0;
    116 }
  • 相关阅读:
    在GDI+中如何实现以左下角为原点的笛卡尔坐标系
    html中内联元素和块元素的区别、用法以及联系
    HttpClient超时设置
    springMVC实现文件上传
    IDEA生成serialVersionUID的警告
    java中两个字符串如何比较大小
    gerrit简版教程
    mysql中OPTIMIZE TABLE的作用及使用
    mysql慢查询日志分析
    checkStype和findBugs校验
  • 原文地址:https://www.cnblogs.com/lnxcj/p/10124793.html
Copyright © 2011-2022 走看看