• [网络流24题] 方格取数问题/骑士共存问题 (最大流->最大权闭合图)


    洛谷传送门 LOJ传送门

    太空飞行计划问题一样,这依然是一道最大权闭合图问题

    “骑士共存问题”是“方格取数问题”的弱化版,本题解不再赘述“骑士共存问题”的做法

    分析题目,如果我们能把所有方格的数都给取上,那么总和是一个定值$sum$

    而题目要求我们取的数不能相邻,我们要想办法最大化$sum$取的数$-sum$没取的数

    现在我们找到了一种取数方案,那么$sum$取的数一定能填补上$sum$没取的数,而且剩下的数总和$>0$,这样,方案才是有收益的

    这不就是最大权闭合图的模型吗?

    把每个格子拆成两个点,分别向源点和汇点连边,流量为它的权值,每个格子向四周连流量为$inf$的边

    最小割割掉了用于填补的部分,用$sum-$最小割就是净收益了

    方格取数问题:

      1 #include <cstdio>
      2 #include <cstring>
      3 #include <iostream>
      4 #include <algorithm>
      5 #define N1 2510
      6 #define M1 30100
      7 #define ll long long
      8 #define dd double
      9 #define inf 0x3f3f3f3f
     10 using namespace std;
     11 
     12 int gint()
     13 {
     14     int ret=0,fh=1;char c=getchar();
     15     while(c<'0'||c>'9'){if(c=='-')fh=-1;c=getchar();}
     16     while(c>='0'&&c<='9'){ret=ret*10+c-'0';c=getchar();}
     17     return ret*fh;
     18 }
     19 int n,m,nm,S,T;
     20 int p[N1],c[N1];
     21 int xx[]={-1,0,1,0},yy[]={0,1,0,-1};  
     22 struct Edge{
     23 int head[N1],to[M1<<1],nxt[M1<<1],flow[M1<<1],cte;
     24 void ae(int u,int v,int F)
     25 {
     26     cte++; to[cte]=v; flow[cte]=F;  
     27     nxt[cte]=head[u]; head[u]=cte;
     28 }
     29 }e;
     30 
     31 int que[M1],hd,tl,dep[N1],cur[N1];
     32 int bfs()
     33 {
     34     int x,j,v;
     35     memset(dep,-1,sizeof(dep)); memcpy(cur,e.head,sizeof(cur));
     36     hd=1,tl=0; que[++tl]=S; dep[S]=0; 
     37     while(hd<=tl)
     38     {
     39         x=que[hd++];
     40         for(j=e.head[x];j;j=e.nxt[j])
     41         {
     42             v=e.to[j]; 
     43             if(dep[v]==-1&&e.flow[j]>0)
     44                 dep[v]=dep[x]+1, que[++tl]=v;
     45         }
     46     }
     47     return dep[T]!=-1;
     48 }
     49 int dfs(int x,int limit)
     50 {
     51     int j,v,flow,ans=0; if(x==T||!limit) return limit;
     52     for(j=cur[x];j;j=e.nxt[j])
     53     {
     54         cur[x]=j; v=e.to[j];
     55         if( dep[v]==dep[x]+1 && (flow=dfs(v,min(e.flow[j],limit))) )
     56         {
     57             limit-=flow; ans+=flow;
     58             e.flow[j]-=flow; e.flow[j^1]+=flow;
     59             if(!limit) break;
     60         }
     61     }
     62     return ans;
     63 }
     64 int Dinic()
     65 {
     66     int mxflow=0;
     67     while(bfs())
     68         mxflow+=dfs(S,inf);
     69     return mxflow;
     70 }
     71 
     72 int a[N1];
     73 int check(int x,int y){ 
     74     if(x<1||y<1||x>n||y>m) return 0; return 1;}
     75 int id(int x,int y){ return (x-1)*m+y; }
     76 
     77 int main()
     78 {
     79     scanf("%d%d",&n,&m); nm=n*m; 
     80     int i,j,k,d,da,db,sum=0,ans; S=2*nm+1,T=2*nm+2; e.cte=1;
     81     for(i=1;i<=n;i++) for(j=1;j<=m;j++)
     82     {
     83         d=id(i,j); a[d]=gint(); sum+=a[d];
     84         e.ae(S,d,a[d]), e.ae(d,S,0);
     85         e.ae(d+nm,T,a[d]), e.ae(T,d+nm,0);
     86     }
     87     for(i=1;i<=n;i++) for(j=1;j<=m;j++)
     88     {
     89         da=id(i,j);
     90         for(k=0;k<4;k++) 
     91         if(check(i+xx[k],j+yy[k]))
     92         {
     93             db=id(i+xx[k],j+yy[k])+nm;
     94             e.ae(da,db,inf), e.ae(db,da,0);
     95         }
     96     }
     97     ans=sum-Dinic();
     98     printf("%d
    ",(sum-ans)/2+ans);
     99     return 0;
    100 }

    骑士共存问题: 只需要把点权改成1 加几个特判就行了

      1 #include <cstdio>
      2 #include <cstring>
      3 #include <iostream>
      4 #include <algorithm>
      5 #define L1 205
      6 #define N1 80050
      7 #define M1 400010
      8 #define ll long long
      9 #define dd double
     10 #define inf 0x3f3f3f3f
     11 using namespace std;
     12 
     13 int gint()
     14 {
     15     int ret=0,fh=1;char c=getchar();
     16     while(c<'0'||c>'9'){if(c=='-')fh=-1;c=getchar();}
     17     while(c>='0'&&c<='9'){ret=ret*10+c-'0';c=getchar();}
     18     return ret*fh;
     19 }
     20 int n,m,nn,S,T;
     21 int p[N1],c[N1];
     22 int xx[]={-2,-1,1,2,2,1,-1,-2},yy[]={1,2,2,1,-1,-2,-2,-1};  
     23 struct Edge{
     24 int head[N1],to[M1<<1],nxt[M1<<1],flow[M1<<1],cte;
     25 void ae(int u,int v,int F)
     26 {
     27     cte++; to[cte]=v; flow[cte]=F;  
     28     nxt[cte]=head[u]; head[u]=cte;
     29 }
     30 }e;
     31 
     32 int que[N1],hd,tl,dep[N1],cur[N1];
     33 int bfs()
     34 {
     35     int x,j,v;
     36     memset(dep,-1,sizeof(dep)); memcpy(cur,e.head,sizeof(cur));
     37     hd=1,tl=0; que[++tl]=S; dep[S]=0; 
     38     while(hd<=tl)
     39     {
     40         x=que[hd++];
     41         for(j=e.head[x];j;j=e.nxt[j])
     42         {
     43             v=e.to[j]; 
     44             if(dep[v]==-1&&e.flow[j]>0)
     45                 dep[v]=dep[x]+1, que[++tl]=v;
     46         }
     47     }
     48     return dep[T]!=-1;
     49 }
     50 int dfs(int x,int limit)
     51 {
     52     int j,v,flow,ans=0; if(x==T||!limit) return limit;
     53     for(j=cur[x];j;j=e.nxt[j])
     54     {
     55         cur[x]=j; v=e.to[j];
     56         if( dep[v]==dep[x]+1 && (flow=dfs(v,min(e.flow[j],limit))) )
     57         {
     58             limit-=flow; ans+=flow;
     59             e.flow[j]-=flow; e.flow[j^1]+=flow;
     60             if(!limit) break;
     61         }
     62     }
     63     return ans;
     64 }
     65 int Dinic()
     66 {
     67     int mxflow=0;
     68     while(bfs())
     69         mxflow+=dfs(S,inf);
     70     return mxflow;
     71 }
     72 
     73 int mp[L1][L1];
     74 int check(int x,int y){ 
     75     if(x<1||y<1||x>n||y>n||mp[x][y]) return 0; return 1;}
     76 int id(int x,int y){ return (x-1)*n+y; }
     77 
     78 int main()
     79 {
     80     scanf("%d%d",&n,&m); nn=n*n; 
     81     int i,j,k,d,da,db,x,y,sum=0,ans; S=2*nn+1,T=2*nn+2; e.cte=1;
     82     for(i=1;i<=m;i++) x=gint(), y=gint(), mp[x][y]=1;
     83     for(i=1;i<=n;i++) for(j=1;j<=n;j++)
     84     {
     85         if(mp[i][j]) continue; d=id(i,j); sum++;
     86         e.ae(S,d,1), e.ae(d,S,0);
     87         e.ae(d+nn,T,1), e.ae(T,d+nn,0);
     88     }
     89     for(i=1;i<=n;i++) for(j=1;j<=n;j++)
     90     {
     91         if(mp[i][j]) continue; da=id(i,j); 
     92         for(k=0;k<8;k++) 
     93         if(check(i+xx[k],j+yy[k]))
     94         {
     95             db=id(i+xx[k],j+yy[k])+nn;
     96             e.ae(da,db,inf), e.ae(db,da,0);
     97         }
     98     }
     99     ans=sum-Dinic();
    100     printf("%d
    ",(sum-ans)/2+ans);
    101     return 0;
    102 }
  • 相关阅读:
    文件格式——gff格式
    文件格式——fastq格式
    Java 8 新特性:1-函数式接口
    10分钟学会JAVA注解(annotation)
    spring MVC 乱码问题
    Tomcat 连接池详解
    DBCP连接池配置参数说明
    spring 事务无效解决方法
    spring mvc 存取值
    使用Criteria 实现两表的左外连接,返回根对象
  • 原文地址:https://www.cnblogs.com/guapisolo/p/10290618.html
Copyright © 2020-2023  润新知