zoukankan      html  css  js  c++  java
  • 【ARC074F】Lotus Leaves 最小割

    Description

    给你一个n*m网格图,有起点荷叶和终点荷叶,有中转荷叶,其他的格子没东西,一个荷叶可以跳到同一行或者列的另一个荷叶。问最多删掉几个中转荷叶能让起点终点不连通。如果不行输出-1.

    Input

    ​ 第一行是两个正整数R,CR,C

    ​ 接下来是一个R∗CR∗C的字符矩阵,第ii行第jj个字符为ai,jai,j

    ​ 若ai,j′.′ai,j′.′,那么这个格子是水面

    ​ 若ai,j′o′ai,j′o′,那么这个格子是一片荷叶

    ​ 若ai,j′S′ai,j′S′或者′T′′T′,那么这个格子是标记了S,TS,T的荷叶

    Output

    ​ 如果没有解,那么输出-1

    ​ 否则输出最少需要删除的个数

    Sample Input

    Case 1:
    3 3
    S.o
    .o.
    o.T
    
    Case 2:
    3 4
    S...
    .oo.
    ...T
    
    Case 3:
    4 3
    .S.
    .o.
    .o.
    .T.
    
    Case 4:
    10 10
    .o...o..o.
    ....o.....
    ....oo.oo.
    ..oooo..o.
    ....oo....
    ..o..o....
    o..o....So
    o....T....
    ....o.....
    ........oo
    

    Sample Output

    Case 1:
    2
    
    Case 2:
    0
    
    Case 3:
    -1
    
    Case 4:
    5
    

    HINT

    ​ 1≤R,C≤1001≤R,C≤100

    ​ S,TS,T只出现一次

    Sol

    考察选手会不会写最大流算法。

    对于每行和每列建一个点,然后S向S所在行和列对应的点连inf,T所在的行和列对应的点向T连inf,对于每个荷叶((i,j)),连边(i->j+n,j+n->i),之后跑最大流即可出解。

    Code

    #include <bits/stdc++.h>
    using namespace std;
    int n,m,S,T,cnt,inf=1e9,sx,sy,tx,ty,hed[1005],d[1005],nex[50005],to[50005],val[50005],ans;queue<int>q;char ch;
    void add(int x,int y,int z)
    {
        to[cnt]=y;val[cnt]=z;nex[cnt]=hed[x];hed[x]=cnt++;
        to[cnt]=x;val[cnt]=0;nex[cnt]=hed[y];hed[y]=cnt++;
    }
    bool bfs()
    {
        while(!q.empty()) q.pop();memset(d,0,sizeof(d));d[S]=1;q.push(S);
        while(!q.empty())
        {
            int x=q.front();q.pop();
            for(int i=hed[x];i!=-1;i=nex[i]) if(!d[to[i]]&&val[i]){d[to[i]]=d[x]+1;if(to[i]==T) return 1;q.push(to[i]);}
        }
        return 0;
    }
    int dfs(int x,int mf)
    {
        if(x==T) return mf;int tmp=mf;
        for(int i=hed[x];i!=-1;i=nex[i]) if(d[to[i]]==d[x]+1&&val[i])
        {
            int k=dfs(to[i],min(val[i],tmp));
            if(!k) d[to[i]]=0;
            tmp-=k;val[i]-=k;val[i^1]+=k;
            if(!tmp) break;
        }
        return mf-tmp;
    }
    int main()
    {
        scanf("%d%d",&n,&m);T=n+m+1;memset(hed,-1,sizeof(hed));
        for(int i=1;i<=n;i++) for(int j=1;j<=m;j++)
        {
            cin>>ch;
            if(ch=='S') add(S,i,inf),add(S,j+n,inf),sx=i,sy=j;
            if(ch=='T') add(i,T,inf),add(j+n,T,inf),tx=i,ty=j;
            if(ch=='o') add(i,j+n,1),add(j+n,i,1);
        }
        if(sx==tx||sy==ty) return puts("-1"),0;
        while(bfs()) ans+=dfs(0,inf*2);
        printf("%d
    ",ans);
    }
    
  • 相关阅读:
    uIP tcp/ip协议分析及其在嵌入式系统中的应用
    围棋学习网站 (updating)
    几种代价函数
    浅谈围棋自学入门 写给想自学围棋的业余爱好者
    在 Ubuntu Natty 中解除系统托盘限制
    MATLAB中的CELL用法
    支持向量机(SVM)
    成功思维的三十个模式
    Microsoft Kinect SDK vs PrimeSense OpenNI
    生命中的选择
  • 原文地址:https://www.cnblogs.com/CK6100LGEV2/p/9449093.html
Copyright © 2011-2022 走看看