• ARC074F Lotus Leaves


    题意简述:给一个(N*M(N,M<=100))的网格图,其中只有为'o'能走,给定一个起点和终点,每次可以从点((i,j))跳到任意点((i,k)(1<=k<=m))或点((k,j)(1<=k<=n)),问最少删掉多少个点可以使起点无法到达终点。

    有一个非常沙雕的做法,基本会网络流的都能想到(除了我这个一开始把范围看错的沙雕),就直接拆点然后裸最小割,总共有(2*n*m)个点,(2*n*m)条边。

    然后有一个稍微优秀一点的做法就是考虑一个点可以跳到其所在行与所在列,那么我们将行列连边,得到的就是一个二分图,然后跑一遍最小割就ok了,总共有(n+m)个点

    //沙雕版
    #include<cstdio>
    #include<queue>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define id(i,j) ((i-1)*m+j)
    const int N=210,inf=1e9;
    struct fk{int to,nxt,w;}e[N*N*N*2];
    int head[N*N*2],cnt=1;
    int dis[N*N*2],n,m,Sx,Sy,Tx,Ty,mp[N][N],S,T,ans,tot;
    char s[N];
    queue<int> q;
    void add(int u,int v,int w){e[++cnt].to=v;e[cnt].nxt=head[u];e[cnt].w=w;head[u]=cnt;}
    bool bfs(){
        memset(dis,63,sizeof(dis));
        dis[S]=0;q.push(S);
        while(!q.empty()){
            int u=q.front();q.pop();
            for(int i=head[u],v;i;i=e[i].nxt)
                if(e[i].w&&dis[v=e[i].to]>dis[u]+1)
                    dis[v]=dis[u]+1,q.push(v);
        }
        return dis[T]<inf;
    }
    int dfs(int u,int flow){
        if(u==T||!flow)return flow;
        int now=0;
        for(int i=head[u],v;i;i=e[i].nxt)
            if(e[i].w&&dis[v=e[i].to]==dis[u]+1){
                int f=dfs(v,min(flow-now,e[i].w));
                e[i].w-=f;e[i^1].w+=f;now+=f;
            }
        if(!now)dis[u]=-1;
        return now;
    }
    void dinic(){for(;bfs();ans+=dfs(S,inf));}
    int main(){
        scanf("%d%d",&n,&m);tot=n*m;
        S=0;T=tot*2+1;
        for(int i=1;i<=n;i++){
            scanf("%s",s+1);
            for(int j=1;j<=m;j++)
                if(s[j]!='.'){
                    if(s[j]=='o'){
                        mp[i][j]=1;
                        add(id(i,j),id(i,j)+tot,1);
                        add(id(i,j)+tot,id(i,j),0);
                    }
                    else{
                        if(s[j]=='S')mp[i][j]=1,Sx=i,Sy=j;
                        if(s[j]=='T')mp[i][j]=1,Tx=i,Ty=j;
                        add(id(i,j),id(i,j)+tot,inf);
                        add(id(i,j)+tot,id(i,j),0);
                    }
                }
        }
        add(S,id(Sx,Sy),inf);
        add(id(Sx,Sy),S,0);
        add(id(Tx,Ty)+tot,T,inf);
        add(T,id(Tx,Ty)+tot,0);
        if(Sx==Tx||Sy==Ty){puts("-1");return 0;}
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++){
                if(mp[i][j]){
                    for(int k=1;k<=n;k++)
                        if(k!=i&&mp[k][j])
                            add(id(i,j)+tot,id(k,j),inf),add(id(k,j),id(i,j)+tot,0);
                    for(int k=1;k<=m;k++)
                        if(k!=j&&mp[i][k])
                            add(id(i,j)+tot,id(i,k),inf),add(id(i,k),id(i,j)+tot,0);
                }
            }
        dinic();
        printf("%d
    ",ans);
    }
    
    //优秀版
    #include<cstdio>
    #include<queue>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int N=510,inf=1e9;
    struct fk{int to,nxt,w;}e[200010];
    int head[N],cnt=1;
    int dis[N],n,m,Sx,Sy,Tx,Ty,S,T,ans;
    char s[N][N];
    queue<int> q;
    void add(int u,int v,int w){e[++cnt].to=v;e[cnt].nxt=head[u];e[cnt].w=w;head[u]=cnt;}
    bool bfs(){
        memset(dis,63,sizeof(dis));
        dis[S]=0;q.push(S);
        while(!q.empty()){
            int u=q.front();q.pop();
            for(int i=head[u],v;i;i=e[i].nxt)
                if(e[i].w&&dis[v=e[i].to]>dis[u]+1)
                    dis[v]=dis[u]+1,q.push(v);
        }
        return dis[T]<inf;
    }
    int dfs(int u,int flow){
        if(u==T||!flow)return flow;
        int now=0;
        for(int i=head[u],v;i;i=e[i].nxt)
            if(e[i].w&&dis[v=e[i].to]==dis[u]+1){
                int f=dfs(v,min(flow-now,e[i].w));
                e[i].w-=f;e[i^1].w+=f;now+=f;
            }
        if(!now)dis[u]=-1;
        return now;
    }
    void dinic(){for(;bfs();ans+=dfs(S,inf));}
    int main(){
        scanf("%d%d",&n,&m);S=0;T=n+m+1;
        for(int i=1;i<=n;i++)
            scanf("%s",s[i]+1);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                if(s[i][j]=='S')Sx=i,Sy=j;
                else if(s[i][j]=='T')Tx=i,Ty=j;
                else if(s[i][j]=='o')add(i,j+n,1),add(j+n,i,0),add(j+n,i,1),add(i,j+n,0);
        if(Sx==Tx||Sy==Ty){puts("-1");return 0;}
        add(S,Sx,inf);add(Sx,S,0);
        add(S,Sy+n,inf);add(Sy+n,S,0);
        add(Tx,T,inf);add(T,Tx,0);
        add(Ty+n,T,inf);add(T,Ty+n,0);
        dinic();
        printf("%d
    ",ans);
    }
    
  • 相关阅读:
    wireshark和tcpdump抓包TCP乱序和重传怎么办?PCAP TCP排序工具分享
    途游斗地主加密协议分析及破解
    linux下unzip解压报错“symlink error: File name too long”怎么办?提供解决方案。
    GPS NMEA-0183协议常用报文数据格式
    微信出现“已停止访问该网页”或“关于潜在的违法或违规内容”怎么办?如何获取被屏蔽的网页的网址?...
    m3u8视频格式分析
    精确哈克,以贪婪为基础的欺诈式引流法
    某米浏览器黑名单文件破解
    HTTP.sys远程执行代码漏洞
    SNMP协议利用
  • 原文地址:https://www.cnblogs.com/yxc2003/p/10720449.html
Copyright © 2020-2023  润新知