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   }

 

 

 

 

 

 

 

 

posted @ 2012-10-09 23:09  Gu Feiyang  阅读(274)  评论(0)    收藏  举报