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 }
奔跑吧!少年!趁着你还年轻