• hdu1569-方格取数-二分图网络流


    方格取数(2)

    Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
    Total Submission(s): 7211    Accepted Submission(s): 2311


    Problem Description
    给你一个m*n的格子的棋盘,每个格子里面有一个非负数。
    从中取出若干个数,使得任意的两个数所在的格子没有公共边,就是说所取数所在的2个格子不能相邻,并且取出的数的和最大。
     
    Input
    包括多个测试实例,每个测试实例包括2整数m,n和m*n个非负数(m<=50,n<=50)
     
    Output
    对于每个测试实例,输出可能取得的最大的和
     
    Sample Input
    3 3 75 15 21 75 15 28 34 70 5
     
    Sample Output
    188
     
    Author
    ailyanlu
     
    Source
     
      把横纵坐标之和按奇偶分成两组,然后对相邻的点连边的话会发现这是一个二分图,我们求得是最大独立集=|V|-最小覆盖集,最小覆盖集可以用网络流来求,左边集合向右边集合的连边容量为inf的边,S向左集合连边,右集合向T连边容量都是格子里的数,然后跑最大流就是
    最小覆盖集了。
      
     1 #include<bits/stdc++.h> 
     2 using namespace std;  
     3 #define LL long long 
     4 #define mp make_pair
     5 #define pb push_back
     6 #define inf 0x3f3f3f3f
     7 #define pii pair<int,int>
     8 int first[3030],tot,S,T;
     9 int cur[3030],d[3030];
    10 bool vis[3030];
    11 struct Edge{
    12     int v,cap,flow,next;
    13 }e[100010];
    14 int fx[4][2]={-1,0,1,0,0,-1,0,1};
    15 void add(int u,int v,int cap){
    16     //cout<<"u="<<u<<' '<<v<<' '<<cap<<endl;
    17     e[tot]=Edge{v,cap,0,first[u]};
    18     first[u]=tot++;
    19     e[tot]=Edge{u,0,0,first[v]};
    20     first[v]=tot++;
    21 }
    22 int a[55][55];
    23 bool bfs(){
    24     memset(vis,0,sizeof(vis));
    25     queue<int>q;
    26     q.push(0);
    27     d[0]=0;
    28     vis[0]=1;
    29     while(!q.empty()){
    30         int u=q.front();
    31         q.pop();
    32         for(int i=first[u];~i;i=e[i].next){
    33             if(!vis[e[i].v] && e[i].cap>e[i].flow){
    34                 vis[e[i].v]=1;
    35                 d[e[i].v]=d[u]+1;
    36                 q.push(e[i].v);
    37             }
    38         }
    39     }
    40     return vis[T];
    41 }
    42 int dfs(int x,int a){
    43     if(x==T || a==0) return a;
    44     int flow=0,f;
    45     for(int &i=cur[x];~i;i=e[i].next){
    46         if(d[x]+1==d[e[i].v] && (f=dfs(e[i].v,min(a,e[i].cap-e[i].flow)))>0){
    47             e[i].flow+=f;
    48             e[i^1].flow-=f;
    49             flow+=f;
    50             a-=f;
    51             if(a==0) break;
    52         }
    53     }
    54     return flow;
    55 }
    56 int solve(){
    57     int ans=0;
    58     while(bfs()){
    59         for(int i=0;i<=T;++i)cur[i]=first[i];
    60         ans+=dfs(0,inf);
    61     }
    62     return ans;
    63 }
    64 int main(){
    65     int n,m,i,j,k;
    66     while(scanf("%d%d",&n,&m)!=EOF){
    67         LL s=0;
    68         memset(first,-1,sizeof(first));
    69         tot=0;
    70         S=0,T=n*m+1;
    71         for(i=1;i<=n;++i){
    72             for(j=1;j<=m;++j){
    73                 scanf("%d",&a[i][j]);
    74                 s+=a[i][j];
    75                 int d1=(i-1)*m+j;
    76                 if((i+j)%2==0){
    77                     add(S,d1,a[i][j]);
    78                     
    79                     for(k=0;k<4;++k){
    80                         int dx=i+fx[k][0];
    81                         int dy=j+fx[k][1];
    82                         if(dx>0&&dy>0&&dx<=n&&dy<=m){
    83                             int d2=(dx-1)*m+dy;
    84                             add(d1,d2,inf);
    85                         }
    86                     }
    87                 }
    88                 else{
    89                     add(d1,T,a[i][j]);
    90                 }
    91             }
    92         }
    93         cout<<s-solve()<<endl;
    94     }
    95     return 0;
    96 }
  • 相关阅读:
    token原理
    1.系统代码读取配置文件
    redis hash怎么用
    那么都数据库表,那么多不同记录。是怎样都存储在一个key-value数据库的?
    jedis操作redis全指南
    redis列表list
    jedis操作
    redis
    android raw与assets资源
    Zoie Merge Policy
  • 原文地址:https://www.cnblogs.com/zzqc/p/9526935.html
Copyright © 2020-2023  润新知