• 【PowerOJ1741&网络流24题】最长递增子序列问题(最大流)


    题意:

     思路:

    【问题分析】

    第一问时LIS,动态规划求解,第二问和第三问用网络最大流解决。

    【建模方法】

    首先动态规划求出F[i],表示以第i位为开头的最长上升序列的长度,求出最长上升序列长度K。

    1、把序列每位i拆成两个点<i.a>和<i.b>,从<i.a>到<i.b>连接一条容量为1的有向边。

    2、建立附加源S和汇T,如果序列第i位有F[i]=K,从S到<i.a>连接一条容量为1的有向边。

    3、如果F[i]=1,从<i.b>到T连接一条容量为1的有向边。

    4、如果j>i且A[i] < A[j]且F[j]+1=F[i],从<i.b>到<j.a>连接一条容量为1的有向边。

    求网络最大流,就是第二问的结果。把边(<1.a>,<1.b>)(<N.a>,<N.b>)(S,<1.a>)(<N.b>,T)这四条边的容量修改为无穷大,再求一次网络最大流,就是第三问结果。

    【建模分析】

    上述建模方法是应用了一种分层图的思想,把图每个顶点i按照F[i]的不同分为了若干层,这样图中从S出发到T的任何一条路径都是一个满足条件的最长上升子序列。由于序列中每个点要不可重复地取出,

    需要把每个点拆分成两个点。单位网络的最大流就是增广路的条数,所以最大流量就是第二问结果。第三问特殊地要求x1和xn可以重复使用,只需取消这两个点相关边的流量限制,求网络最大流即可。

    实质上也只有两层,不如叫裂点

    单位网络的最大流就是增广路的条数 这个性质需要记住

      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  1000000
     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[N],len[N],nxt[N],dp[N],a[N],dis[N],num[N][2],s,S,T,K,n,tot;
     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     q.push(S),dis[S]=0;
     63     while(!q.empty())
     64     {
     65         int u=q.front();
     66         q.pop();
     67         int e=head[u];
     68         while(e)
     69         {
     70             int v=vet[e];
     71             if(len[e]&&dis[v]==-1)
     72             {
     73                 dis[v]=dis[u]+1;
     74                 q.push(v);
     75             }
     76             e=nxt[e];
     77         }
     78     }
     79     return dis[T]!=-1;
     80 }
     81 
     82 int dfs(int u,int aug)
     83 {
     84     if(u==T) return aug;
     85     int e=head[u],val=0,flow=0;
     86     while(e)
     87     {
     88         int v=vet[e];
     89         if(len[e]&&dis[v]==dis[u]+1)
     90         {
     91             int t=dfs(v,min(len[e],aug));
     92             if(!t)
     93             {
     94                 e=nxt[e];
     95                 continue;
     96             }
     97             flow+=t;
     98             aug-=t;
     99             len[e]-=t;
    100             len[e^1]+=t;
    101             if(!aug) break;
    102         }
    103         e=nxt[e];
    104     }
    105     if(!flow) dis[u]=-1;
    106     return flow;
    107 }
    108 
    109 int maxflow()
    110 {
    111     int res=0;
    112     while(bfs()) res+=dfs(S,INF);
    113     return res;
    114 }
    115 
    116 void solve1()
    117 {
    118     s=0;
    119     rep(i,1,n)
    120      rep(j,0,1) num[i][j]=++s;
    121     S=++s;
    122     T=++s;
    123     rep(i,1,s) head[i]=0;
    124     tot=1;
    125     rep(i,1,n) add(num[i][0],num[i][1],1);
    126     rep(i,1,n)
    127      if(dp[i]==1) add(S,num[i][0],1);
    128     rep(i,1,n)
    129      if(dp[i]==K) add(num[i][1],T,1);
    130     rep(i,1,n)
    131      rep(j,i+1,n)
    132       if(a[j]>a[i]&&dp[j]==dp[i]+1) add(num[i][1],num[j][0],1);
    133     int ans=maxflow();
    134     printf("%d
    ",ans);
    135 }
    136 
    137 void solve2()
    138 {
    139     rep(i,1,s) head[i]=0;
    140     tot=1;
    141     add(num[1][0],num[1][1],INF);
    142     add(num[n][0],num[n][1],INF);
    143     rep(i,2,n-1) add(num[i][0],num[i][1],1);
    144     rep(i,1,n)
    145      if(dp[i]==1)
    146      {
    147          if(i==1||i==n) add(S,num[i][0],INF);
    148           else add(S,num[i][0],1);
    149      }
    150 
    151     rep(i,1,n)
    152      if(dp[i]==K)
    153      {
    154          if(i==1||i==n) add(num[i][1],T,INF);
    155           else add(num[i][1],T,1);
    156      }
    157 
    158     rep(i,1,n)
    159      rep(j,i+1,n)
    160       if(a[j]>a[i]&&dp[j]==dp[i]+1) add(num[i][1],num[j][0],1);
    161     int ans=maxflow();
    162     if(ans>INF) ans=n;
    163     printf("%d
    ",ans);
    164 }
    165 
    166 int main()
    167 {
    168     //freopen("1.in","r",stdin);
    169     n=read();
    170     rep(i,1,n) a[i]=read();
    171     rep(i,1,n)
    172     {
    173         dp[i]=1;
    174         rep(j,1,i-1)
    175          if(a[j]<a[i]) dp[i]=max(dp[i],dp[j]+1);
    176     }
    177     K=1;
    178     rep(i,1,n) K=max(K,dp[i]);
    179     printf("%d
    ",K);
    180     solve1();
    181     solve2();
    182     return 0;
    183 }
  • 相关阅读:
    hdu 4027 Can you answer these queries?
    Codeforces: Empty Triangle
    hdu 3006 The Number of set
    hdu 3645 Code Management System
    进度条作控件代码
    NORMAL
    callback
    三种形状匹配脚本
    移动点动画
    脚本管理
  • 原文地址:https://www.cnblogs.com/myx12345/p/11756287.html
Copyright © 2020-2023  润新知