AtCoder Regular Contest 074F

$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 }
View Code
原文地址:https://www.cnblogs.com/Blue233333/p/8866751.html