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\n",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("\n"); 138 } 139 } 140 return 0; 141 }