HDU 3338 Kakuro Extension

题意:看图就知道大概是个什么意思了,就是每行连续的数之和等于一个规定的数,每列连续的数之和等于一个规定的数。

           

神题啊。。这都可以是网络流。。貌似也只能是网络流了。。直接搜的题解。。觉得建图也不是那么神奇  但是就是觉得真的不可思议。。

首先,流量有下界,是1,那么干脆所有的边的流量都把这个1的部分减掉。

直接贴这个博客上说的:http://www.cnblogs.com/ylfdrib/archive/2010/08/15/1799903.html

建图:

一共有四类点:

1. 构造源点S,汇点T

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

3. 空白格,设为B

4. 有列和的格子,设为C

则可以建边:

1. <S, A> 容量和行和

2. <A, B> 容量为8

3. <B, C> 容量为8

4. <C, T> 容量为列和

最后怎么去填格子里的数字呢?

每个格子里的数字等于1+从行和中流向这个格子的流量和

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <algorithm>
  5 #define INF 0x7fffffff
  6 #define maxn 20010
  7 #define maxm 500000
  8 using namespace std;
  9 int v[maxm],next[maxm],w[maxm];
 10 int first[maxn],d[maxn],work[maxn],q[maxn];
 11 int e,S,T;
 12 int map[105][105];
 13 struct Row{
 14     int x,y,z;
 15 }row[maxn];
 16 struct Col{
 17     int x,y,z;
 18 }col[maxn];
 19 
 20 void init(){
 21     e = 0;
 22     memset(first,-1,sizeof(first));
 23 }
 24 
 25 void add_edge(int a,int b,int c){
 26     //printf("add:%d to %d,cap = %d
",a,b,c);
 27     v[e] = b;w[e] = c;next[e] = first[a];first[a] = e++;
 28     v[e] = a;w[e] = 0;next[e] = first[b];first[b] = e++;
 29 }
 30 
 31 int bfs(){
 32     int rear = 0;
 33     memset(d,-1,sizeof(d));
 34     d[S] = 0;q[rear++] = S;
 35     for(int i = 0;i < rear;i++){
 36         for(int j = first[q[i]];j != -1;j = next[j])
 37             if(w[j] && d[v[j]] == -1){
 38                 d[v[j]] = d[q[i]] + 1;
 39                 q[rear++] = v[j];
 40                 if(v[j] == T)   return 1;
 41             }
 42     }
 43     return 0;
 44 }
 45 
 46 int dfs(int cur,int a){
 47     if(cur == T)    return a;
 48     for(int &i = work[cur];i != -1;i = next[i]){
 49         if(w[i] && d[v[i]] == d[cur] + 1)
 50             if(int t = dfs(v[i],min(a,w[i]))){
 51                 w[i] -= t;w[i^1] += t;
 52                 return t;
 53             }
 54     }
 55     return 0;
 56 }
 57 
 58 int dinic(){
 59     int ans = 0;
 60     while(bfs()){
 61         memcpy(work,first,sizeof(first));
 62         while(int t = dfs(S,INF))   ans += t;
 63     }
 64     return ans;
 65 }
 66 
 67 int cal(int id,int row_cnt){
 68     int cnt = 0,pos = id+row_cnt;
 69     for(int i = first[pos];i != -1;i = next[i])
 70         if(v[i] <= row_cnt) cnt += w[i];
 71     return cnt+1;
 72 }
 73 
 74 int main()
 75 {
 76     int n,m;
 77     char str[10];
 78     while(scanf("%d%d",&n,&m) == 2){
 79         init();
 80         int row_cnt,col_cnt,id;
 81         row_cnt = col_cnt = id = 0;
 82         for(int i = 1;i <= n;i++){
 83             for(int j = 1;j <= m;j++){
 84                 scanf("%s",str);
 85                 if(str[0] == '.'){
 86                     map[i][j] = ++id;
 87                 }else{
 88                     map[i][j] = -1;
 89                     if(str[0] != 'X'){
 90                         int tmp = (str[0]-'0')*100 + (str[1]-'0')*10 + str[2]-'0';
 91                         col[++col_cnt].x = i;
 92                         col[col_cnt].y = j;
 93                         col[col_cnt].z = tmp;
 94                     }
 95                     if(str[4] != 'X'){
 96                         int tmp = (str[4]-'0')*100 + (str[5]-'0')*10 + str[6]-'0';
 97                         row[++row_cnt].x = i;
 98                         row[row_cnt].y = j;
 99                         row[row_cnt].z = tmp;
100                     }
101                 }
102             }
103         }
104         S = 0,T = row_cnt+id+col_cnt+1;
105         for(int i = 1;i <= row_cnt;i++){
106             int x = row[i].x;
107             int y = row[i].y;
108             int cnt_len = 0;
109             for(y = y+1;y <= m;y++){
110                 if(map[x][y] != -1){
111                     cnt_len++;
112                     add_edge(i,row_cnt+map[x][y],8);
113                 }
114                 else   break;
115             }
116             add_edge(S,i,row[i].z-cnt_len);
117         }
118         for(int i = 1;i <= col_cnt;i++){
119             int x = col[i].x;
120             int y = col[i].y;
121             int cnt_len = 0;
122             for(x = x+1;x <= n;x++){
123                 if(map[x][y] != -1){
124                     cnt_len++;
125                     add_edge(row_cnt+map[x][y],row_cnt+id+i,8);
126                 }
127                 else    break;
128             }
129             add_edge(row_cnt+id+i,T,col[i].z-cnt_len);
130         }
131         dinic();
132         for(int i = 1;i <= n;i++){
133             for(int j = 1;j <= m;j++){
134                 if(map[i][j] == -1) printf("_ ");
135                 else    printf("%d ",cal(map[i][j],row_cnt));
136             }
137             printf("
");
138         }
139     }
140     return 0;
141 }
View Code
原文地址:https://www.cnblogs.com/zhexipinnong/p/3386959.html