• hdu 3338 最大流 ****


    题意:

    黑格子右上代表该行的和,左下代表该列下的和

    链接:点我

    这题可以用网络流做。以空白格为节点,假设流是从左流入,从上流出的,流入的容量为行和,流出来容量为列和,其余容量不变。求满足的最大流。由于流量有上下限限制,可以给每个数都减掉1,则填出来的数字范围为0—8, 就可以用单纯的网络流搞定了。求出来再加上就可以了。

    这一题主要是在建图

    建图:

    一共有四类点:

    1. 构造源点ST,汇点ED

    2. 有行和的格子,即上面有值的格子,此类节点设为A

    3. 空白格,设为B

    4. 有列和的格子,即下面有值的格子,设为C

    则可以建边:

    1. ST------------A         容量:行和

    2. A----------- B          容量:8

    3. B------------C          容量:8

    4. C------------ED          容量:列和

    当然,反向边容量都置为0。

    就是这么难~~

      1 #include<iostream>
      2 #include<cstring>
      3 #include<cstdio>
      4 using namespace std;
      5 
      6 
      7 #define INF 999999999
      8 #define MAXN 14000
      9 #define RE(x) (x)^1
     10 
     11 int head[MAXN];
     12 int map[120][120];
     13 int st,ed;
     14 struct Edge
     15 {
     16     int v,next;
     17     int val;
     18     Edge(){}
     19     Edge( int V , int NEXT , int W = 0 ):v(V),next(NEXT),val(W){}
     20 }edge[500000];
     21 
     22 struct gg
     23 {
     24     int x,y;
     25     int val;
     26 }row[MAXN],col[MAXN];
     27 int emp,row_num,col_num;
     28 int lvl[MAXN], gap[MAXN];
     29 int cnt_edge;
     30 int n,m,T;
     31 int empty[MAXN];
     32 
     33 void Insert_Edge( int u , int v , int flow = 0 ) {
     34 
     35     edge[cnt_edge] = Edge(v,head[u],flow);
     36     head[u] = cnt_edge++;
     37     edge[cnt_edge] = Edge(u,head[v]);
     38     head[v] = cnt_edge++;
     39 
     40 }
     41 
     42 void Init(){
     43     cnt_edge = 0;
     44     memset(head,-1,sizeof(head));
     45      memset(lvl, 0, sizeof (lvl));
     46     memset(gap, 0, sizeof (gap));
     47 }
     48 
     49 int dfs(int u, int flow)
     50 {
     51     if (u==ed) {
     52         return flow;
     53     }
     54     int tf = 0, sf, mlvl = ed-1;
     55     for (int i= head[u]; i != -1; i = edge[i].next) {
     56         if (edge[i].val > 0) { 
     57             if (lvl[u] ==lvl[edge[i].v]+1) {  
     58                 sf = dfs(edge[i].v, min(flow-tf, edge[i].val));
     59                 edge[i].val -= sf;
     60                 edge[RE(i)].val += sf;
     61                 tf += sf;
     62                 if (lvl[st] >=ed) {
     63                     return tf;
     64                 }
     65                 if (tf == flow) {
     66                     break;
     67                 }
     68             }
     69             mlvl = min(mlvl, lvl[edge[i].v]);
     70         }
     71     }
     72     if (tf == 0) {
     73         --gap[lvl[u]];
     74         if (!gap[lvl[u]]) {
     75             lvl[st] =ed;
     76         }
     77         else {
     78             lvl[u] = mlvl+1;
     79             ++gap[lvl[u]];
     80         }
     81     }
     82     return tf;
     83 }
     84 
     85 int sap()
     86 {
     87     int ans = 0;
     88     gap[0]=ed;
     89     while (lvl[st] <ed) {
     90         ans += dfs(st, INF);
     91     }
     92     return ans;
     93 }
     94 
     95 int print( int tp ) {
     96     int ans = 0;
     97     int id = tp + row_num+1;
     98     for( int i = head[id] ; i != -1 ; i = edge[i].next ) {
     99         int v = edge[i].v;
    100         if( v <=row_num+1 )
    101         { 
    102           ans+= edge[i].val;
    103           break;
    104         }
    105     }
    106     return ans+1;
    107 }
    108 
    109 int main()
    110 
    111 {
    112 
    113     int i,j;
    114 
    115     char s[15];
    116 
    117     while(scanf("%d%d",&n,&m)!=-1)
    118     {
    119         emp=row_num=col_num=0;
    120         for(i=0;i<n;i++)
    121         for(j=0;j<m;j++)
    122         {
    123             scanf("%s",s);
    124             if(s[0]=='.')
    125             {
    126                 map[i][j]=++emp;    
    127             }
    128             else
    129             {
    130                 map[i][j]=-1;
    131                 if(s[4]!='X')
    132                 {
    133                         int tp=(s[4]-'0')*100+(s[5]-'0')*10+s[6]-'0';
    134                         row[++row_num].x=i;
    135                         row[row_num].y=j;
    136                         row[row_num].val=tp;
    137                         
    138     
    139                 }
    140                 if(s[0]!= 'X' ) {
    141                         int tp = (s[0]-'0')*100+(s[1]-'0')*10+s[2]-'0';
    142                         col[++col_num].x = i;
    143                         col[col_num].y = j;
    144                         col[col_num].val = tp;
    145                     }
    146     
    147             }
    148                 
    149         }
    150         T=emp+col_num+row_num+2;
    151         st=1;
    152         ed=T;
    153         Init();
    154         for(i=1;i<=row_num;i++)
    155         {
    156             int pos = i;
    157             int x = row[i].x;
    158             int y = row[i].y;
    159             int cnt_len = 0;
    160             for( y=y+1; y <m ; y++ ) {
    161                 if( map[x][y] != -1 ) {
    162                     cnt_len++;
    163             Insert_Edge(i+1, row_num+ map[x][y]+1,8);
    164                 } else break;
    165             }
    166             Insert_Edge(st,pos+1,row[i].val-cnt_len);
    167         }
    168         
    169         for( i = 1 ; i <=col_num ; i++ ) {
    170             int pos =i+1+row_num+emp;
    171             int x = col[i].x;
    172             int y = col[i].y;
    173             int cnt_len = 0;
    174             for( x=x+1 ; x < n ; x++ ) {
    175                 if( map[x][y] != -1 ) {
    176                     cnt_len++;
    177             Insert_Edge(row_num+ map[x][y]+1,pos,8);
    178                 
    179                 } else break;
    180             }
    181             Insert_Edge(pos,ed,col[i].val-cnt_len);
    182         }
    183         sap();
    184         for(i=0;i<n;i++)
    185         {
    186         for(j=0;j<m;j++)
    187         {
    188         
    189             if(map[i][j]==-1)
    190             printf("_ ");
    191             else
    192             printf("%d ",print(map[i][j]));    
    193         }
    194         printf("
    ");
    195     }    
    196     }
    197     
    198     return 0;
    199 }
    2015/5/26

    kuangbin大法:

      1 /*
      2  * HDU 3338 Kakuro Extension
      3  * 题目意思就是在n*m的格子中,有黑白两种格子。要在白格子中填入数字1~9
      4  * 每一段横竖连续的白格子的和是知道的。
      5  * 求出一种满足的,保证有解。
      6  * 最大流。
      7  * 按照横竖段进行编号。然后行进列出,构造图形。
      8  *
      9  * 为了保证填入的数字是1~9,所以一开始每个格子减掉了1,相应的流入和流出都减掉。
     10  * 然后格子的边的赋值为8.
     11  * 还有就是要记录下相应边的编号,便于输出结果。
     12  *
     13  */
     14 
     15 #include <iostream>
     16 #include <string.h>
     17 #include <algorithm>
     18 #include <stdio.h>
     19 using namespace std;
     20 
     21 const int MAXN=20010;
     22 const int MAXM=200010;
     23 const int INF=0x3f3f3f3f;
     24 struct Node
     25 {
     26     int to,next,cap;
     27 }edge[MAXM];
     28 int tol;
     29 int head[MAXN];
     30 int gap[MAXN],dis[MAXN],pre[MAXN],cur[MAXN];
     31 void init()
     32 {
     33     tol=0;
     34     memset(head,-1,sizeof(head));
     35 }
     36 void addedge(int u,int v,int w,int rw=0)
     37 {
     38     edge[tol].to=v;edge[tol].cap=w;edge[tol].next=head[u];head[u]=tol++;
     39     edge[tol].to=u;edge[tol].cap=rw;edge[tol].next=head[v];head[v]=tol++;
     40 }
     41 int sap(int start,int end,int nodenum)
     42 {
     43     memset(dis,0,sizeof(dis));
     44     memset(gap,0,sizeof(gap));
     45     memcpy(cur,head,sizeof(head));
     46     int u=pre[start]=start,maxflow=0,aug=-1;
     47     gap[0]=nodenum;
     48     while(dis[start]<nodenum)
     49     {
     50         loop:
     51         for(int  &i=cur[u];i!=-1;i=edge[i].next)
     52         {
     53             int v=edge[i].to;
     54             if(edge[i].cap&&dis[u]==dis[v]+1)
     55             {
     56                 if(aug==-1||aug>edge[i].cap)
     57                     aug=edge[i].cap;
     58                 pre[v]=u;
     59                 u=v;
     60                 if(v==end)
     61                 {
     62                     maxflow+=aug;
     63                     for(u=pre[u];v!=start;v=u,u=pre[u])
     64                     {
     65                         edge[cur[u]].cap-=aug;
     66                         edge[cur[u]^1].cap+=aug;
     67                     }
     68                     aug=-1;
     69                 }
     70                 goto loop;
     71             }
     72         }
     73         int mindis=nodenum;
     74         for(int i=head[u];i!=-1;i=edge[i].next)
     75         {
     76             int v=edge[i].to;
     77             if(edge[i].cap&&mindis>dis[v])
     78             {
     79                 cur[u]=i;
     80                 mindis=dis[v];
     81             }
     82         }
     83         if((--gap[dis[u]])==0)break;
     84         gap[dis[u]=mindis+1]++;
     85         u=pre[u];
     86     }
     87     return maxflow;
     88 }
     89 
     90 char str[110][110][10];
     91 int lx[110][110];//存横条的标号
     92 int ly[110][110];//存竖条的标号
     93 int num[20010];//记录lx,ly数组中出现的次数,因为题目要求填入的数字是1~9,所以先全部变1,相应的流要减少
     94 int id[110][110];//相应的边的编号,便于最后统计结果
     95 
     96 int main()
     97 {
     98     //freopen("in.txt","r",stdin);
     99     //freopen("out.txt","w",stdout);
    100     int n,m;
    101     while(scanf("%d%d",&n,&m)==2)
    102     {
    103         for(int i=0;i<n;i++)
    104             for(int j=0;j<m;j++)
    105                 scanf("%s",str[i][j]);
    106         init();
    107         int tt=0;//结点标号
    108         memset(lx,0,sizeof(lx));
    109         memset(ly,0,sizeof(ly));
    110         memset(num,0,sizeof(num));
    111         for(int i=0;i<n;i++)
    112             for(int j=0;j<m;j++)
    113             {
    114                 if(strcmp(str[i][j],".......")!=0)continue;
    115                 if(j==0 || lx[i][j-1]==0)lx[i][j]=++tt;
    116                 else lx[i][j]=lx[i][j-1];
    117                 num[lx[i][j]]++;
    118             }
    119         for(int j=0;j<m;j++)
    120             for(int i=0;i<n;i++)
    121             {
    122                 if(strcmp(str[i][j],".......")!=0)continue;
    123                 if(i==0 || ly[i-1][j]==0)ly[i][j]=++tt;
    124                 else ly[i][j]=ly[i-1][j];
    125                 num[ly[i][j]]++;
    126             }
    127         int start=0,end=tt+1,nodenum=tt+2;
    128         for(int i=0;i<n;i++)
    129             for(int j=0;j<m;j++)
    130                 if(strcmp(str[i][j],".......")==0)
    131                 {
    132                     addedge(lx[i][j],ly[i][j],8);
    133                     id[i][j]=tol-2;//记录下来
    134                 }
    135         for(int i=0;i<n;i++)
    136             for(int j=0;j<m;j++)
    137             {
    138                 if(str[i][j][3]!='\')continue;
    139                 if(str[i][j][0]!='X')
    140                 {
    141                     int tmp=(str[i][j][0]-'0')*100+(str[i][j][1]-'0')*10+(str[i][j][2]-'0');
    142                     if(ly[i+1][j]!=0)
    143                         addedge(ly[i+1][j],end,tmp-num[ly[i+1][j]]);
    144                 }
    145                 if(str[i][j][4]!='X')
    146                 {
    147                     int tmp=(str[i][j][4]-'0')*100+(str[i][j][5]-'0')*10+(str[i][j][6]-'0');
    148                     if(lx[i][j+1]!=0)
    149                         addedge(start,lx[i][j+1],tmp-num[lx[i][j+1]]);
    150                 }
    151             }
    152         sap(start,end,nodenum);
    153         for(int i=0;i<n;i++)
    154         {
    155             for(int j=0;j<m;j++)
    156             {
    157                 if(j>0)printf(" ");
    158                 if(strcmp(str[i][j],".......")!=0)printf("_");
    159                 else printf("%c",'0'+9-edge[id[i][j]].cap);
    160             }
    161             printf("
    ");
    162         }
    163     }
    164     return 0;
    165 }
    View Code
  • 相关阅读:
    centos安装composer
    fmt.Printf()
    php进程,线程,异步
    php异步处理
    php安装swoole扩展
    冒泡排序
    快速排序
    php的foreach指针
    无密钥登陆
    ubuntu18.04切换阿里云源
  • 原文地址:https://www.cnblogs.com/cnblogs321114287/p/4531639.html
Copyright © 2020-2023  润新知