hdu 3338 最大流 ****

题意:

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("\n");

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("\n");

162         }

163     }

164     return 0;

165 }
View Code

 

你可能感兴趣的:(HDU)