• 【PowerOJ1739&网络流24题】魔术球问题(最大流)


    题意:

     思路:

    0.【问题分析】

    枚举答案转化为判定性问题,然后最小路径覆盖,可以转化成二分图最大匹配,从而用最大流解决。

    【建模方法】

    枚举答案A,在图中建立节点1..A。如果对于i<j有i+j为一个完全平方数,连接一条有向边(i,j)。该图是有向无环图,求最小路径覆盖。如果刚好满足最小路径覆盖数等于N,那么A是一个可行解,在所有可行

    解中找到最大的A,即为最优解。

    具体方法可以顺序枚举A的值,当最小路径覆盖数刚好大于N时终止,A-1就是最优解。

    【建模分析】

    由于是顺序放球,每根柱子上的球满足这样的特征,即下面的球编号小于上面球的编号。抽象成图论,把每个球看作一个顶点,就是编号较小的顶点向编号较大的顶点连接边,条件是两个球可以相邻,即

    编号之和为完全平方数。每根柱子看做一条路径,N根柱子要覆盖掉所有点,一个解就是一个路径覆盖。

    最小路径覆盖数随球的数量递增不递减,满足单调性,所以可以枚举答案(或二分答案),对于特定的答案求出最小路径覆盖数,一个可行解就是最小路径覆盖数等于N的答案,求出最大的可行解就是最

    优解。本问题更适合枚举答案而不是二分答案,因为如果顺序枚举答案,每次只需要在残量网络上增加新的节点和边,再增广一次即可。如果二分答案,就需要每次重新建图,大大增加了时间复杂度。

    输出方案时候不需要重新跑一遍,虽然最后的残余网络比答案多两个点和一些边,但合法那部分的残余网络还是一样的

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 typedef long long ll;
      4 typedef unsigned int uint;
      5 typedef unsigned long long ull;
      6 typedef long double ld;
      7 typedef pair<int,int> PII;
      8 typedef pair<ll,ll> Pll;
      9 typedef vector<int> VI;
     10 typedef vector<PII> VII;
     11 typedef pair<ll,ll>P;
     12 #define N  100010
     13 #define M  3000000
     14 #define INF 1e9
     15 #define fi first
     16 #define se second
     17 #define MP make_pair
     18 #define pb push_back
     19 #define pi acos(-1)
     20 #define mem(a,b) memset(a,b,sizeof(a))
     21 #define rep(i,a,b) for(int i=(int)a;i<=(int)b;i++)
     22 #define per(i,a,b) for(int i=(int)a;i>=(int)b;i--)
     23 #define lowbit(x) x&(-x)
     24 #define Rand (rand()*(1<<16)+rand())
     25 #define id(x) ((x)<=B?(x):m-n/(x)+1)
     26 #define ls p<<1
     27 #define rs p<<1|1
     28 
     29 const ll MOD=1e9+7,inv2=(MOD+1)/2;
     30       double eps=1e-6;
     31       int dx[4]={-1,1,0,0};
     32       int dy[4]={0,0,-1,1};
     33 
     34 int head[N],vet[M],len[M],nxt[M],dis[N],p[N],vis[N],tot,S,T,s;
     35 
     36 int read()
     37 {
     38    int v=0,f=1;
     39    char c=getchar();
     40    while(c<48||57<c) {if(c=='-') f=-1; c=getchar();}
     41    while(48<=c&&c<=57) v=(v<<3)+v+v+c-48,c=getchar();
     42    return v*f;
     43 }
     44 
     45 void add(int a,int b,int c)
     46 {
     47     nxt[++tot]=head[a];
     48     vet[tot]=b;
     49     len[tot]=c;
     50     head[a]=tot;
     51 
     52     nxt[++tot]=head[b];
     53     vet[tot]=a;
     54     len[tot]=0;
     55     head[b]=tot;
     56 }
     57 
     58 bool bfs()
     59 {
     60     queue<int>q;
     61     //rep(i,1,s) dis[i]=-1;
     62     rep(i,1,s) dis[i]=dis[i+5000]=-1;
     63     dis[T]=-1;
     64     q.push(S),dis[S]=0;
     65     while(!q.empty())
     66     {
     67         int u=q.front();
     68         q.pop();
     69         int e=head[u];
     70         while(e)
     71         {
     72             int v=vet[e];
     73             if(len[e]&&dis[v]==-1)
     74             {
     75                 dis[v]=dis[u]+1;
     76                 q.push(v);
     77             }
     78             e=nxt[e];
     79         }
     80     }
     81     return dis[T]!=-1;
     82 }
     83 
     84 int dfs(int u,int aug)
     85 {
     86     if(u==T) return aug;
     87     int e=head[u],val=0,flow=0;
     88     while(e)
     89     {
     90         int v=vet[e];
     91         if(len[e]&&dis[v]==dis[u]+1)
     92         {
     93             int t=dfs(v,min(len[e],aug));
     94             if(!t)
     95             {
     96                 e=nxt[e];
     97                 continue;
     98             }
     99             flow+=t;
    100             aug-=t;
    101             len[e]-=t;
    102             len[e^1]+=t;
    103             if(!aug) break;
    104         }
    105         e=nxt[e];
    106     }
    107     if(!flow) dis[u]=-1;
    108     return flow;
    109 }
    110 
    111 int maxflow()
    112 {
    113     int res=0;
    114     while(bfs()) res+=dfs(S,INF);
    115     return res;
    116 }
    117 
    118 int main()
    119 {
    120     int n=read();
    121     S=0; T=10000;
    122     rep(i,0,T) head[i]=0;
    123     tot=1;
    124     s=0;
    125     int sum=0;
    126     while(1)
    127     {
    128         s++;
    129         rep(i,1,s-1)
    130          if(sqrt(s+i)==(int)sqrt(s+i)) add(i,s+5000,1);
    131         add(S,s,1);
    132         add(s+5000,T,1);
    133         sum+=maxflow();
    134         int t=s-sum;
    135         if(t>n) break;
    136     }
    137     printf("%d
    ",s-1);
    138     rep(i,1,s-1)
    139     {
    140         int e=head[i];
    141         while(e)
    142         {
    143             int v=vet[e];
    144             if(!len[e]){p[i]=v-5000; break;}
    145             e=nxt[e];
    146         }
    147     }
    148     rep(i,1,s-1)
    149     {
    150         if(vis[i]) continue;
    151         int u=i;
    152         while(u!=-5000)
    153         {
    154             vis[u]=1;
    155             printf("%d ",u);
    156             u=p[u];
    157         }
    158         printf("
    ");
    159     }
    160     return 0;
    161 }
  • 相关阅读:
    快学Scala-第八章 继承
    快学scala-第七章 包和引入
    快学Scala-第六章 对象
    快学Scala-第五章 类
    快学Scala-第四章 映射和元组
    快学Scala-第三章 数组相关操作
    快学Scala-第二章 控制结构和函数
    快学Scala-第一章 基础
    ReLu(Rectified Linear Units)激活函数
    软件工程的发展史
  • 原文地址:https://www.cnblogs.com/myx12345/p/11755720.html
Copyright © 2020-2023  润新知