light oj 1262
题意: 给出一个N*M的矩形格子, 每个格子里边有一个数字,数字的范围在[1,100], 现在给出了两种对角线的和,让求出每个格子中的数字是多少。

思路: 这道题开始想了很长时间都没有思路, 后来一下子就想到了。 这道题是一道求和的问题。可以转化成网络流问题。 但是这里有一个问题就是如何决定节点, 如何建边。 由于每个点要计算两次。 每个点的值是固定的。因此我们可以让一个作为流入的,一个作为流出的。
途中的每个格子是一个节点。另外新建立2(n+m-1)个节点表示不同的对角线(姑姐叫做对角线点)。 源点到这些点的流量为对角线的和。 对于第一种对角线, 对角线点到所涉及的点的流量为正无穷。 对于第二种对角线点,所涉及的格子的点到这个点的流量为正无穷。 最后看流量是多少,直接得出答案就行了。
但是这样wa了。原因是要求每个格子中的点的值在1-100之间。 所以至少要流1,所以我们在每个对角线点的流量要减去其涉及点的个数, 还要求其最大流量不超过100,所以其流量要为99. 因此这样最后可以由反向流就可以得到答案。
AC代码:
View Code
1 #include <cstdio> 2 #include <cstring> 3 #include <string> 4 #include <iostream> 5 #include <queue> 6 using namespace std; 7 const int N = 204, M = 1000000, INF = 1<<28; 8 9 struct EDGE 10 { 11 int u, v, cap, next; 12 }edge[M]; 13 14 int num, head[N*N], dis[N*N], pre[N*N], cur[N*N], gap[N*N]; 15 int ans[N][N], n, m, k; 16 17 void add(int u, int v, int cap) 18 { 19 edge[num].u = u; 20 edge[num].v = v; 21 edge[num].cap = cap; 22 edge[num].next = head[u]; 23 head[u] = num++; 24 } 25 26 void init() 27 { 28 int w; 29 num = 0; 30 memset(head, -1, sizeof(head)); 31 scanf("%d%d", &n, &m); 32 k = n+m-1; 33 for(int i=0; i<k; i++) 34 { 35 scanf("%d", &w); 36 for(int j=0; j<=k; ++j) 37 { 38 if(i-j>=0 && j<m && i-j<n) 39 { 40 w--; 41 add(n*m+i, (i-j)*m+j, 99); 42 add((i-j)*m+j, n*m+i, 0); 43 } 44 } 45 add(n*m+2*k+1, n*m+i, w); 46 add(n*m+i, n*m+2*k+1, 0); 47 } 48 for(int i=0; i<k; i++) 49 { 50 scanf("%d", &w); 51 for(int j=0; j<=k; ++j) 52 { 53 if(i-j>=0 && m-1-j>=0 && i-j<n) 54 { 55 w--; 56 add((i-j)*m+m-1-j, n*m+k+i, 99); 57 add(n*m+k+i, (i-j)*m+m-1-j, 0); 58 } 59 } 60 add(n*m+k+i, n*m+2*k+2, w); 61 add(n*m+2*k+2, n*m+k+i, 0); 62 } 63 } 64 65 void SAP(int s,int t) //sap模版 66 { 67 memset(gap,0,sizeof(gap)); 68 memset(dis,0,sizeof(dis)); 69 int i; 70 for(i=0;i<=t;i++) 71 { 72 cur[i] = head[i]; 73 } 74 int top=s; 75 gap[s]=t+1; 76 int maxflow=0,flow=INF; 77 while(dis[s] < t+1) 78 { 79 for(i=cur[top];i != -1;i = edge[i].next) 80 { 81 if(edge[i].cap > 0 && dis[top] == dis[edge[i].v] + 1) 82 break; 83 } 84 if(i != -1) 85 { 86 cur[top] = i; 87 int v = edge[i].v; 88 if(edge[i].cap < flow) 89 { 90 flow = edge[i].cap; 91 } 92 top = v; 93 pre[v] = i; 94 if(top == t) 95 { 96 maxflow += flow; 97 while(top != s) 98 { 99 edge[pre[top]].cap -= flow; 100 edge[pre[top]^1].cap += flow; 101 top = edge[pre[top]^1].v; 102 } 103 flow = INF; 104 } 105 } 106 else 107 { 108 if(--gap[dis[top]] == 0) 109 { 110 break; 111 } 112 dis[top] = t+1; 113 cur[top] = head[top]; 114 for(int j=head[top];j != -1;j=edge[j].next) 115 { 116 if(edge[j].cap > 0 && dis[edge[j].v] + 1 < dis[top]) 117 { 118 dis[top] = dis[edge[j].v] + 1; 119 cur[top] = j; 120 } 121 } 122 gap[dis[top]]++; 123 if(top != s) 124 { 125 top = edge[pre[top]^1].v; 126 } 127 } 128 } 129 } 130 131 132 void solve() 133 { 134 SAP(n*m+2*k+1, n*m+2*k+2); 135 int u, v, w; 136 memset(ans, 0, sizeof(ans)); 137 for(int i=1; i<num; i+=2) 138 { 139 u = edge[i].u; 140 v = edge[i].v; 141 if(u>=0 && u<n*m) 142 { 143 ans[u/m][u%m] = edge[i].cap; 144 } 145 if(v>=0 && v<n*m) 146 { 147 ans[v/m][v%m] = edge[i].cap; 148 } 149 } 150 151 for(int i=0; i<n; i++) 152 { 153 printf("%d", ans[i][0]+1); 154 for(int j=1; j<m; j++) 155 printf(" %d", ans[i][j]+1); 156 printf("\n"); 157 } 158 } 159 160 int main() 161 { 162 int t; 163 scanf("%d", &t); 164 for(int i=1; i<=t; i++) 165 { 166 init(); 167 printf("Case %d:\n",i); 168 solve(); 169 } 170 return 0; 171 }


浙公网安备 33010602011771号