• 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
  • 相关阅读:
    windows10输入法评价
    找水王
    团队项目第九天
    团队项目第八天
    团队项目第七天
    团队项目第六天
    团队项目第四天
    团队项目第五天
    团队项目第三天
    团队项目第二天
  • 原文地址:https://www.cnblogs.com/Blue233333/p/8866751.html
Copyright © 2020-2023  润新知