uva 563(最大流)

题意:在一个街道网格中有若干个银行,现在有小偷去偷,在偷完钱后由于不能被警察抓到所有任意两个小偷不能走同一条街道(点和边都不行)逃跑,问你是否能把所有的银行都偷到。

思路:这道题就是最大流,先建图后套模版就行了。借这道题用了邝大神的sap模版果断效率很高,对于这道题由于点的容量有限制所以需要拆点,然而一开始我没有读清楚题意所以没有拆点导致怎么也算不对。。。后来一想不对劲改过来立马ac了。首先每个点拆成两个结点(一个专门连出边,一个入边)从出边点连一条边指向入边点流量为1。然后在网格之间建立双向变。最后我们设立一个源点,从原点出发到所有银行流量为1表示有小偷去偷,然后再设立一个汇点使所有边上的结点都指向它。

见图过程到此为止接下来就是套模板,判断流量是否等于银行数。

代码如下:

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <cstdlib>
  5 #include <algorithm>
  6 #include <utility>
  7 #include <queue>
  8 #include <stack>
  9 #include <vector>
 10 
 11 using namespace std;
 12 
 13 int n, sa, sb, m;
 14 
 15 //sap by kuangbin
 16 const int MAXN = 100010;//点数的最大值
 17 const int MAXM = 400010;//边数的最大值
 18 const int INF = 0x3f3f3f3f;
 19 struct Edge
 20 {
 21     int to,next,cap,flow;
 22 } edge[MAXM]; //注意是MAXM
 23 int tol;
 24 int head[MAXN];
 25 int gap[MAXN],dep[MAXN],cur[MAXN];
 26 void init()
 27 {
 28     tol = 0;
 29     memset(head,-1,sizeof(head));
 30 }
 31 void addedge(int u,int v,int w,int rw = 0)
 32 {
 33     edge[tol].to = v;
 34     edge[tol].cap = w;
 35     edge[tol].flow = 0;
 36     edge[tol].next = head[u];
 37     head[u] = tol++;
 38     edge[tol].to = u;
 39     edge[tol].cap = rw;
 40     edge[tol].flow = 0;
 41     edge[tol].next = head[v];
 42     head[v] = tol++;
 43 }
 44 int Q[MAXN];
 45 void BFS(int start,int end)
 46 {
 47     memset(dep,-1,sizeof(dep));
 48     memset(gap,0,sizeof(gap));
 49     gap[0] = 1;
 50     int front = 0, rear = 0;
 51     dep[end] = 0;
 52     Q[rear++] = end;
 53     while(front != rear)
 54     {
 55         int u = Q[front++];
 56         for(int i = head[u]; i != -1; i = edge[i].next)
 57         {
 58             int v = edge[i].to;
 59             if(dep[v] != -1)continue;
 60             Q[rear++] = v;
 61             dep[v] = dep[u] + 1;
 62             gap[dep[v]]++;
 63         }
 64     }
 65 }
 66 int S[MAXN];
 67 int sap(int start,int end,int N)
 68 {
 69     BFS(start,end);
 70     memcpy(cur,head,sizeof(head));
 71     int top = 0;
 72     int u = start;
 73     int ans = 0;
 74     while(dep[start] < N)
 75     {
 76         if(u == end)
 77         {
 78             int Min = INF;
 79             int inser;
 80             for(int i = 0; i < top; i++)
 81                 if(Min > edge[S[i]].cap - edge[S[i]].flow)
 82                 {
 83                     Min = edge[S[i]].cap - edge[S[i]].flow;
 84                     inser = i;
 85                 }
 86             for(int i = 0; i < top; i++)
 87             {
 88                 edge[S[i]].flow += Min;
 89                 edge[S[i]^1].flow -= Min;
 90             }
 91             ans += Min;
 92             top = inser;
 93             u = edge[S[top]^1].to;
 94             continue;
 95         }
 96         bool flag = false;
 97         int v;
 98         for(int i = cur[u]; i != -1; i = edge[i].next)
 99         {
100             v = edge[i].to;
101             if(edge[i].cap - edge[i].flow && dep[v]+1 == dep[u])
102             {
103 
104                 flag = true;
105                 cur[u] = i;
106                 break;
107             }
108         }
109         if(flag)
110         {
111             S[top++] = cur[u];
112             u = v;
113             continue;
114         }
115         int Min = N;
116         for(int i = head[u]; i != -1; i = edge[i].next)
117             if(edge[i].cap - edge[i].flow && dep[edge[i].to] < Min)
118             {
119                 Min = dep[edge[i].to];
120                 cur[u] = i;
121             }
122         gap[dep[u]]--;
123         if(!gap[dep[u]])return ans;
124         dep[u] = Min + 1;
125         gap[dep[u]]++;
126         if(u != start)u = edge[S[--top]^1].to;
127     }
128     return ans;
129 }
130 
131 inline int ch(int x, int y, int isout){return (isout?(x*sb+y):(x*sb+y+sa*sb));}
132 void buildmap()
133 {
134     init();
135     n = sa*sb*2+2;
136     for(int i=1; i<=sa; i++)
137     for(int j=1; j<=sb; j++)
138     addedge(ch(i,j,0), ch(i,j,1),1);
139     for(int i=1; i<=sa; i++)
140     {
141         for(int j=1; j<sb; j++)
142         {
143             addedge(ch(i,j,1), ch(i,j+1,0), 1);
144             addedge(ch(i,j+1,1), ch(i,j,0), 1);
145         }
146     }
147     for(int i=1; i<sa; i++)
148     {
149         for(int j=1; j<=sb; j++)
150         {
151             addedge(ch(i,j,1), ch(i+1,j,0), 1);
152             addedge(ch(i+1,j,1), ch(i,j,0), 1);
153         }
154     }
155     for(int i=1; i<=sb; i++)
156     {
157         addedge(ch(1,i,1), n-1, 1);
158         addedge(ch(sa,i,1), n-1, 1);
159     }
160     for(int i=2; i<sa; i++)
161     {
162         addedge(ch(i,1,1), n-1, 1);
163         addedge(ch(i,sb,1), n-1, 1);
164     }
165 }
166 
167 int main()
168 {
169 //    freopen("in.txt", "r", stdin);
170 
171     int T, a, b;
172     scanf("%d", &T);
173     while(T--)
174     {
175         scanf("%d%d%d", &sa, &sb, &m);
176         buildmap();
177         for(int i=0; i<m; i++)
178         {
179             scanf("%d%d", &a, &b);
180             addedge(0, ch(a,b,0), 1);
181         }
182         int ans = sap(0,n-1, n);
183         if(ans==m)printf("possible\n");
184         else printf("not possible\n");
185     }
186     return 0;
187 }
View Code

 

posted @ 2013-12-25 22:42  张小豪  阅读(262)  评论(0编辑  收藏  举报