[SCOI2007]蜥蜴 题解
[SCOI2007]蜥蜴
板子题啊 , 我好菜啊写错了两次
拆点
拆点后把柱子高度作为边权 , 当前点能到的点相互连边权无限的边 , 如果当前点能到边界 , 就改向汇点连边(注意一个点只能往汇点连最多一条边)
把一开始有蜥蜴的点与源点连边权1的点
然后就没了
真实板子题
我菜啊
1 #include<cmath> 2 #include<queue> 3 #include<cstdio> 4 #include<cstring> 5 #include<cstdlib> 6 #include<iostream> 7 #include<algorithm> 8 #define APART puts("----------------------") 9 #define debug 1 10 #define FILETEST 0 11 #define inf 10010 12 #define ll long long 13 #define ha 998244353 14 #define INF 0x7fffffff 15 #define INF_T 9223372036854775807 16 #define DEBUG printf("%s %d\n",__FUNCTION__,__LINE__) 17 18 namespace chino{ 19 20 inline void setting(){ 21 #if FILETEST 22 freopen("test.in", "r", stdin); 23 freopen("test.me.out", "w", stdout); 24 #endif 25 return; 26 } 27 28 inline int read(){ 29 char c = getchar(), up = c; int num = 0; 30 for(; c < '0' || c > '9'; up = c, c = getchar()); 31 for(; c >= '0' && c <= '9'; num = (num << 3) + (num << 1) + (c ^ '0'), c = getchar()); 32 return up == '-' ? -num : num; 33 } 34 35 int n, m, d; 36 int cntE = -1; 37 int S, T; 38 int maxflow, totL; 39 int dep[inf]; 40 int head[inf]; 41 int cur[inf]; 42 char str[inf][inf]; 43 struct Edge{ 44 int to; 45 int flow; 46 int next; 47 }e[inf << 1]; 48 std::queue <int> Q; 49 50 inline void AddEdge(int from, int to, int flow){ 51 ++cntE; 52 e[cntE].to = to; 53 e[cntE].flow = flow; 54 e[cntE].next = head[from]; 55 head[from] = cntE; 56 return; 57 } 58 59 inline bool check(int x, int y){ 60 return x < 1 || y < 1 || x > n || y > m; 61 } 62 63 inline bool checkGG(int x, int y){ 64 return sqrt(x * x + y * y) > d; 65 } 66 67 inline bool BFS(int s, int t){ 68 memset(dep, -1, sizeof dep); 69 memcpy(cur, head, sizeof cur); 70 while(!Q.empty()) 71 Q.pop(); 72 dep[s] = 1; 73 Q.push(s); 74 while(!Q.empty()){ 75 int x = Q.front(); 76 Q.pop(); 77 for(int i = head[x]; i ^ -1; i = e[i].next){ 78 int y = e[i].to; 79 if(dep[y] == -1 && e[i].flow){ 80 dep[y] = dep[x] + 1; 81 Q.push(y); 82 } 83 } 84 } 85 return dep[t] ^ -1; 86 } 87 88 int DFS(int s, int limit){ 89 if(limit == 0 || s == T) 90 return limit; 91 int f = 0; 92 int flow = 0; 93 for(int i = cur[s]; i ^ -1; i = e[i].next){ 94 cur[s] = i; 95 int Min = std::min(limit, e[i].flow); 96 int to = e[i].to; 97 if(dep[to] == dep[s] + 1 && (f = DFS(to, Min))){ 98 flow += f; 99 limit -= f; 100 e[i].flow -= f; 101 e[i ^ 1].flow += f; 102 if(limit == 0) 103 break; 104 } 105 } 106 return flow; 107 } 108 109 inline void dinic(int s, int t){ 110 while(BFS(s, t)) 111 maxflow += DFS(s, INF); 112 return; 113 } 114 115 inline int main(){ 116 memset(head, -1, sizeof head); 117 n = read(); 118 m = read(); 119 d = read(); 120 S = n * m + 1; 121 T = S + 1; 122 S <<= 1, T <<= 1; 123 for(int i = 1; i <= n; i++) 124 scanf("%s", str[i] + 1); 125 for(int i = 1; i <= n; i++){ 126 for(int j = 1; j <= m; j++){ 127 bool flag = 0; 128 int now = str[i][j] - '0'; 129 if(now == 0) 130 continue; 131 AddEdge(i * m - m + j, (i * m - m + j) + n * m, now); 132 AddEdge((i * m - m + j) + n * m, i * m - m + j, 0); 133 for(int a = -d; a <= d; a++){ 134 for(int b = -d; b <= d; b++){ 135 int nowx = i + a; 136 int nowy = j + b; 137 if(str[nowx][nowy] == '0' || checkGG(a, b) || (a == 0 && b == 0)) 138 continue; 139 if(check(nowx, nowy)){ 140 if(flag == 0){ 141 AddEdge((i * m - m + j) + n * m, T, INF); 142 AddEdge(T, (i * m - m + j) + n * m, 0); 143 flag = 1; 144 } 145 } else { 146 AddEdge((i * m - m + j) + n * m, nowx * m - m + nowy, INF); 147 AddEdge(nowx * m - m + nowy, (i * m - m + j) + n * m, 0); 148 } 149 } 150 } 151 } 152 } 153 for(int i = 1; i <= n; i++) 154 scanf("%s", str[i] + 1); 155 for(int i = 1; i <= n; i++){ 156 for(int j = 1; j <= m; j++) 157 if(str[i][j] == 'L'){ 158 AddEdge(S, i * m - m + j, 1); 159 AddEdge(i * m - m + j, S, 0); 160 ++totL; 161 } 162 } 163 dinic(S, T); 164 printf("%d\n", totL - maxflow); 165 return 0; 166 } 167 168 }//namespace chino 169 170 int main(){return chino::main();}