zoukankan      html  css  js  c++  java
  • 洛谷P2765 魔术球问题

    题目链接:https://www.luogu.org/problemnew/show/P2765

    知识点:  最大流

    解题思路:

      本题所有边的容量均为 (1)。

      从 (1) 开始加入数字,将这个数拆成两个点:(P_1) 连源点,(P_2) 连汇点,然后枚举所有比它小并且与它加起来是完全平方数的正整数 (Num) ,从 (Num) 的 (P_1) 连一条边到目前要加入的数字的 (P_2)。

      建完边后在之前的残量网络的基础上跑 (Dinic),如果没有新的流量通过,说明需要用新的柱子来放新加入的数,将新加入的数字作为新的链表的链表头。

      当需要用的柱子数大于 (n) 时,停止加入数字,利用跑 (Dinic) 的过程中建立起来的链表输出答案。

    AC代码:

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 const int MAXN=10000;
     4 const int INF=0x3f3f3f3f;
     5 
     6 struct edge{
     7     int to,cap,rev;
     8 };
     9 int next_pt[MAXN];
    10 vector<edge> G[MAXN];
    11 bool used[MAXN];
    12 void add_edge(int from,int to,int cap){
    13     G[from].push_back((edge){to,cap,G[to].size()});
    14     G[to].push_back((edge){from,0,G[from].size()-1});
    15 }
    16 int dfs(int v,int t,int f){
    17     if(v==t)    return f;
    18     used[v]=true;
    19     for(int i=0;i<G[v].size();i++){
    20         edge &e=G[v][i];
    21         if(!used[e.to] && e.cap>0){
    22             int d=dfs(e.to,t,min(f,e.cap));
    23             if(d>0){    //d>0,代表有新的流量注入
    24                 e.cap-=d;
    25                 G[e.to][e.rev].cap+=d;
    26                 next_pt[v/2]=e.to/2;    //用链表记录下一个数
    27                 return d;
    28             }
    29         }
    30     }
    31     return 0;
    32 }
    33 int max_flow(int s,int t){
    34     int flow=0;
    35     for(;;){
    36         memset(used,0,sizeof(used));
    37         int f=dfs(s,t,INF);
    38         if(f==0)    return flow;
    39         flow+=f;
    40     }
    41 }
    42 bool vis[MAXN];
    43 int head[100];
    44 int main(){
    45     int n;
    46     scanf("%d",&n);
    47     int s=0,t=MAXN-1;
    48     int max_num=0,had=0;
    49     while(had<=n){
    50         max_num++;
    51         add_edge(s,max_num<<1,1);   //P1
    52         add_edge(max_num<<1|1,t,1); //P2
    53         for(int i=1;;i++){
    54             if(i*i>max_num){
    55                 int tmp=i*i-max_num;
    56                 if(tmp>=max_num)    break;
    57                 add_edge(tmp<<1,max_num<<1|1,1);
    58             }
    59         }
    60         if(!max_flow(s,t)){
    61             had++;
    62             head[had]=max_num;
    63         }
    64     }
    65     printf("%d
    ",max_num-1);
    66     for(int i=1;i<=n;i++){
    67         if(!vis[head[i]]){
    68             for(int j=head[i];j!=0&&j!=t/2;j=next_pt[j]){
    69                 vis[j]=true;
    70                 printf("%d ",j);
    71             }
    72             puts("");
    73         }
    74     }
    75 
    76     return 0;
    77 }
    “这些年我一直提醒自己一件事情,千万不要自己感动自己。大部分人看似的努力,不过是愚蠢导致的。什么熬夜看书到天亮,连续几天只睡几小时,多久没放假了,如果这些东西也值得夸耀,那么富士康流水线上任何一个人都比你努力多了。人难免天生有自怜的情绪,唯有时刻保持清醒,才能看清真正的价值在哪里。”
  • 相关阅读:
    Java核心技术 卷一 笔记四 库类的直接使用
    Java核心技术 卷一 笔记三 大数值及数组
    Java核心技术 卷一 笔记2 字符串的复制
    Java核心技术 卷一 笔记1
    修改css 样式后, hover事件 不生效
    修改 element ui input 输入框 样式不生效问题
    css3 计算属性
    Vue3 改动系列
    浏览器实现,向下滑动 鼠标滚轮,页面横向移动
    linux ceont0s7 vue 打包压缩图片 一直报错
  • 原文地址:https://www.cnblogs.com/Blogggggg/p/9320740.html
Copyright © 2011-2022 走看看