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 }
    “这些年我一直提醒自己一件事情,千万不要自己感动自己。大部分人看似的努力,不过是愚蠢导致的。什么熬夜看书到天亮,连续几天只睡几小时,多久没放假了,如果这些东西也值得夸耀,那么富士康流水线上任何一个人都比你努力多了。人难免天生有自怜的情绪,唯有时刻保持清醒,才能看清真正的价值在哪里。”
  • 相关阅读:
    Servlet的几种跳转(转)
    Java String.split()用法小结(转)
    表单数据提交的方法
    gedit文本编辑器乱码解决办法
    J-Link烧写bootloader到mini2440的Nor Flash
    虚拟机安装Fedora10系统遇到异常
    linux系统忘记root密码怎么办?
    编译busybox时出错及解决方案
    source insight代码查看器如何自定义添加文件类型
    < Objective-C >文件操作-NSFileHandle
  • 原文地址:https://www.cnblogs.com/Blogggggg/p/9320740.html
Copyright © 2011-2022 走看看