Codeforces Gym 100203I I - I WIN 网络流最大流

I - I WIN
Time Limit: 2 Sec

Memory Limit: 256 MB

题目连接

http://acm.hust.edu.cn/vjudge/contest/view.action?cid=87954#problem/I

Description

Given an n × m rectangular tile with each square marked with one of the letters W, I, and N, find the maximal number of triominoes that can be cut from this tile such that the triomino has W and N on the ends and I in the middle (that is, it spells WIN in some order). Of course the only possible triominoes are the one with three squares in a straight line and the L-shaped ones, and the triominoes can't overlap.

Input

First line contains two integers n and m with 1 ≤ m, n ≤ 22. The next n lines contain m characters each (only the letters W, I and N).

Output

Output a single integer: the maximum number of nonoverlapping WIN-triominoes.

Sample Input

4 4
WIIW
NNNN
IINN
WWWI

Sample Output

5

HINT

 

题意

    给你一个n*m的矩形,最多能找出多少不重复的WIN块?

题解

          建图方法:

                      S-1-W-1-I-1-I-1-N-T

           注意点考虑到有一个I可能会与两个不同位置的W,N相连 

还有就是模版6666

代码:

#include <cstdio>
#include <cmath>
#include <cstring>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <set>
#include <vector>
#include <queue>
#include <typeinfo>
#include <map>
#include <stack>
typedef long long ll;
using namespace std;
inline ll read()
{
    ll x=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9')
    {
        if(ch=='-')f=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9')
    {
        x=x*10+ch-'0';
        ch=getchar();
    }
    return x*f;
}
//***************************
namespace NetFlow
{
    const int MAXN=100000,MAXM=500000,inf=1e9;
    struct Edge
    {
        int v,c,f,nx;
        Edge() {}
        Edge(int v,int c,int f,int nx):v(v),c(c),f(f),nx(nx) {}
    } E[MAXM];
    int G[MAXN],cur[MAXN],pre[MAXN],dis[MAXN],gap[MAXN],N,sz;
    void init(int _n)
    {
        N=_n,sz=0; memset(G,-1,sizeof(G[0])*N);
    }
    void link(int u,int v,int c)
    {
        E[sz]=Edge(v,c,0,G[u]); G[u]=sz++;
        E[sz]=Edge(u,0,0,G[v]); G[v]=sz++;
    }
    int ISAP(int S,int T)
    {//S -> T
        int maxflow=0,aug=inf,flag=false,u,v;
        for (int i=0;i<N;++i)cur[i]=G[i],gap[i]=dis[i]=0;
        for (gap[S]=N,u=pre[S]=S;dis[S]<N;flag=false)
        {
            for (int &it=cur[u];~it;it=E[it].nx)
            {
                if (E[it].c>E[it].f&&dis[u]==dis[v=E[it].v]+1)
                {
                    if (aug>E[it].c-E[it].f) aug=E[it].c-E[it].f;
                    pre[v]=u,u=v; flag=true;
                    if (u==T)
                    {
                        for (maxflow+=aug;u!=S;)
                        {
                            E[cur[u=pre[u]]].f+=aug;
                            E[cur[u]^1].f-=aug;
                        }
                        aug=inf;
                    }
                    break;
                }
            }
            if (flag) continue;
            int mx=N;
            for (int it=G[u];~it;it=E[it].nx)
            {
                if (E[it].c>E[it].f&&dis[E[it].v]<mx)
                {
                    mx=dis[E[it].v]; cur[u]=it;
                }
            }
            if ((--gap[dis[u]])==0) break;
            ++gap[dis[u]=mx+1]; u=pre[u];
        }
        return maxflow;
    }
    bool bfs(int S,int T)
    {
        static int Q[MAXN]; memset(dis,-1,sizeof(dis[0])*N);
        dis[S]=0; Q[0]=S;
        for (int h=0,t=1,u,v,it;h<t;++h)
        {
            for (u=Q[h],it=G[u];~it;it=E[it].nx)
            {
                if (dis[v=E[it].v]==-1&&E[it].c>E[it].f)
                {
                    dis[v]=dis[u]+1; Q[t++]=v;
                }
            }
        }
        return dis[T]!=-1;
    }
    int dfs(int u,int T,int low)
    {
        if (u==T) return low;
        int ret=0,tmp,v;
        for (int &it=cur[u];~it&&ret<low;it=E[it].nx)
        {
            if (dis[v=E[it].v]==dis[u]+1&&E[it].c>E[it].f)
            {
                if (tmp=dfs(v,T,min(low-ret,E[it].c-E[it].f)))
                {
                    ret+=tmp; E[it].f+=tmp; E[it^1].f-=tmp;
                }
            }
        }
        if (!ret) dis[u]=-1; return ret;
    }
    int dinic(int S,int T)
    {
        int maxflow=0,tmp;
        while (bfs(S,T))
        {
            memcpy(cur,G,sizeof(G[0])*N);
            while (tmp=dfs(S,T,inf)) maxflow+=tmp;
        }
        return maxflow;
    }
}
using namespace NetFlow;
char mp[333][333];
int ss[4][2]={-1,0,1,0,0,1,0,-1};
int n,m;
int main()
{
    init(15000);
      n=read();
     m=read();
    for(int i=1; i<=n; i++)
    {
        scanf("%s",mp[i]+1);
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++)
        if(mp[i][j]=='I'){
            link((i-1)*m+j,(i-1)*m+j+500,1);
        }
    }
    for(int i=1; i<=n; i++)
    {
        for(int j=1; j<=m; j++)
        {
            if(mp[i][j]=='W')
            {
                //mpp[n*m+1][(i-1)*m+j]=1;
                link(n*m+1+500,(i-1)*m+j,1);
                for(int e=0; e<4; e++)
                    if(mp[i+ss[e][0]][j+ss[e][1]]=='I')
                    {

                        link((i-1)*m+j,(i+ss[e][0]-1)*m+j+ss[e][1],1);
                    }
            }
            if(mp[i][j]=='I')
            {
                for(int e=0; e<4; e++)
                    if(mp[i+ss[e][0]][j+ss[e][1]]=='N')
                    {
                       link((i-1)*m+j+500,(i+ss[e][0]-1)*m+j+ss[e][1],1);
                    }
            }
            if(mp[i][j]=='N')link((i-1)*m+j,n*m+2+500,1);
        }
    }
    cout<<dinic(n*m+1+500,n*m+1+500+1)<<endl;
  return 0;
}

 

转载于:https://www.cnblogs.com/zxhl/p/4733393.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值