$n leq 300,m leq 300$,$n*m$的格子里有起点有终点有空地有障碍,人会从起点选一个同行或同列空地跳过去,然后一直这样跳到终点。求至少删掉多少格子使得人跳不到终点。
首先S和T同行或同列无解。
这不是裸的最小割嘛。。等会这复杂度不大对
优化:一行里的点要连来连去嘛,每个点都要向同行或同列的所有点连inf边嘛,那咱把这边聚一下,每行每列新开一个点,这一行的所有点连向代表这一行的点,代表这一行的点连向所有这一行的点,这样边从三次方变成了平方。可过。
还有一种建图方法:每行每列开一个点,把一个空地对应的行列连条边,起点向其行列连边,终点其行列向终点连边。
1 //#include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 //#include<time.h> 5 //#include<complex> 6 //#include<queue> 7 #include<algorithm> 8 #include<stdlib.h> 9 using namespace std; 10 11 #define LL long long 12 int qread() 13 { 14 char c; int s=0; while ((c=getchar())<'0' || c>'9'); 15 do s=s*10+c-'0'; while ((c=getchar())>='0' && c<='9'); return s; 16 } 17 18 //Pay attention to '-' and LL of qread!!!! 19 20 int n,m; 21 #define maxn 400011 22 #define maxm 4000011 23 struct Edge{int to,next,cap,flow;}; 24 struct Network 25 { 26 Edge edge[maxm]; int first[maxn],le,n; 27 void clear(int m) {le=2; n=m;} 28 void in(int x,int y,int cap) 29 {Edge &e=edge[le]; e.to=y; e.cap=cap; e.flow=0; e.next=first[x]; first[x]=le++;} 30 void insert(int x,int y,int cap) {in(x,y,cap); in(y,x,0);} 31 int s,t,dis[maxn],cur[maxn],que[maxn],head,tail; 32 bool bfs() 33 { 34 memset(dis,0,sizeof(dis)); dis[s]=1; 35 head=0; tail=1; que[0]=s; 36 while (head!=tail) 37 { 38 int now=que[head++]; 39 for (int i=first[now];i;i=edge[i].next) 40 { 41 Edge &e=edge[i]; 42 if (e.cap>e.flow && dis[e.to]==0) 43 { 44 dis[e.to]=dis[now]+1; 45 que[tail++]=e.to; 46 } 47 } 48 } 49 return dis[t]; 50 } 51 int dfs(int x,int a) 52 { 53 if (x==t || !a) return a; 54 int flow=0,f; 55 for (int &i=cur[x];i;i=edge[i].next) 56 { 57 Edge &e=edge[i]; 58 if (dis[e.to]==dis[x]+1 && (f=dfs(e.to,min(a,e.cap-e.flow)))>0) 59 { 60 e.flow+=f; flow+=f; 61 edge[i^1].flow-=f; a-=f; 62 if (!a) break; 63 } 64 } 65 return flow; 66 } 67 int Dinic(int s,int t) 68 { 69 this->s=s; this->t=t; 70 int ans=0; 71 while (bfs()) 72 { 73 for (int i=1;i<=n;i++) cur[i]=first[i]; 74 ans+=dfs(s,0x3f3f3f3f); 75 } 76 return ans; 77 } 78 }g; 79 80 char mp[311][311]; int id[311][311]; 81 82 int main() 83 { 84 // freopen("trade.in","r",stdin); 85 // freopen("trade.out","w",stdout); 86 n=qread(); m=qread(); 87 for (int i=1;i<=n;i++) scanf("%s",mp[i]+1); 88 int sx,sy,tx,ty,s,t,tot=0; 89 for (int i=1;i<=n;i++) 90 for (int j=1;j<=m;j++) if (mp[i][j]!='.') 91 { 92 id[i][j]=++tot; 93 if (mp[i][j]=='S') sx=i,sy=j,s=tot; 94 if (mp[i][j]=='T') tx=i,ty=j,t=tot; 95 } 96 97 if (sx==tx || sy==ty) {puts("-1"); return 0;} 98 99 g.clear(tot*2+n+m); 100 for (int i=1;i<=tot;i++) if (i!=s && i!=t) g.insert(i,i+tot,1); 101 for (int i=1;i<=n;i++) 102 for (int j=1;j<=m;j++) if (id[i][j]) 103 { 104 if (id[i][j]==s) 105 { 106 g.insert(s,tot*2+i,0x3f3f3f3f); 107 g.insert(tot*2+i,s,0x3f3f3f3f); 108 g.insert(s,tot*2+n+j,0x3f3f3f3f); 109 g.insert(tot*2+n+j,s,0x3f3f3f3f); 110 } 111 else 112 { 113 g.insert(id[i][j]+tot,tot*2+i,0x3f3f3f3f); 114 g.insert(tot*2+i,id[i][j],0x3f3f3f3f); 115 g.insert(id[i][j]+tot,tot*2+n+j,0x3f3f3f3f); 116 g.insert(tot*2+n+j,id[i][j],0x3f3f3f3f); 117 } 118 } 119 printf("%d ",g.Dinic(s,t)); 120 return 0; 121 }