P4003 infinite loop

The meaning of problems

First, a black and white checkerboard stained watertight to such board, if and only if the respective directions of each black point of the nozzle mouthpiece are connected on a white point. In other words, we want the minimum black point and white point to match the maximum number, while the number of operations is not difficult to think of a minimum cost maximum flow.

For a description of one side \ ((w, c) \ ) represents the capacity \ (W \) , a cost of \ (C \) .

Each point we split into up and down four points, even from a point source in all directions to the presence of black spots spout \ ((1,0) \) side, the presence of white spots in all directions to sink spout even \ ((1,0) \) side.

Then for each pair of adjacent points, the corresponding nozzle is connected to the white point from a black dot orifice \ ((1,0) \) side. For example \ ((i, j) \ ) and \ ((I-. 1, J) \) , \ ((i, j) \ ) is a black dot, from the \ ((i, j) \ ) in the direction of to \ ((i-1, j ) \) under the direction of the connected edges.

Now consider how to deal with rotation, we might as well discuss classification.

Defined \ ((i, j, 0 /1/2/3) \) represent \ ((i, j) \ ) about the vertical point of FIG.

1. Only a spout:
The following diagram, for example, other empathy:

clockwise rotation \ (90 \) degrees:
In this case the nozzle moved from the right.
If it is a black spot, then the ((i, j, 0) \) \ to \ ((i, j, 3 ) \) connected \ ((1,1) \) side, which means that the \ (S \) flows \ ((i, j, 0 ) \) capacity of \ (1 \) stream may be, and by changing the direction of this edge \ ((i, j + 1,2 ) \) match, instead of \ ((. 1-I, J,. 1) \) .
If this is the white point, we have from the \ ((i, j, 3 ) \) to \ ((i, j, 0 ) \) connected \ ((1,1) \) side, which means \ (( i, j, 3) \) after matching contribution can flow through this edge of the sink.

The following all default \ ((i, j) \ ) is a black spot. (White dot will start and end in turn)

Counterclockwise rotation \ (90 \) degrees:
Similarly, the even edge \ (((i, j, 0), (i, j, 2), 1,1,) \)

Rotation \ (180 \) degrees:
Similarly, the even edge \ (((I, J, 0), (I, J,. 1), 1,1) \) .

2. Two spout:
Because straight prohibit rotation, we only need to consider \ (L \) type can be.

FIG still less an example only, the other the same way:

clockwise rotation \ (90 \) degrees:
In this case the nozzle does not disappear right, and becomes the downward direction, so from \ ((i, j, 0 ) \) to \ ((i, j, 1 ) \) connected \ ((1,1) \) side.

Counterclockwise rotation \ (90 \) degrees:
this time the upward spout not disappeared, and the right becomes the left, so the \ ((i, j, 3 ) \) to \ ((i, j, 2) \) even \ ((1,1) \) side.

Rotation \ (180 \) of:
time line from the lower left and right turns, cost \ (2 \) , we found that even the two sides just before we had this effect.

3. Three spout
still the following figure as an example.

If appreciated that the above two, this would soon know, even then only given edge.

Clockwise \ (90 \) degrees:
from \ ((i, j, 2 ) \) to \ ((i, j, 1 ) \) connected \ ((1,1) \) side.
Counterclockwise rotation \ (90 \) degrees:
from \ ((i, j, 3 ) \) to \ ((i, j, 1 ) \) connected \ ((1,1) \) side.
Rotation \ (180 \) degree:
from \ ((i, j, 0 ) \) to \ ((i, j, 1 ) \) connected \ ((1,2) \) side.

code:

#include<bits/stdc++.h>
using namespace std;
#define re register
#define pii pair<int,int>
#define mkp make_pair
#define fir first
#define sec second
const int maxn=2010;
const int inf=1e9;
const int dx[]={-1,1,0,0};
const int dy[]={0,0,-1,1};
int n,m,tot=1,cnt_edge=1,S,T,sum;
int head[maxn*5],dis[maxn*5],col[maxn*5];
int a[maxn][maxn];
int id[maxn][maxn][5];//0->up,1->down,2->left,3->right.
bool vis[maxn*5];
struct edge{int to,nxt,flow,cost;}e[maxn*50];
inline int read()
{
    char c=getchar();re int res=0,f=1;
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9')res=res*10+c-'0',c=getchar();
    return res*f;
}
inline int change(int k)
{
    re int op=2333;
    if(k==0)op=0;
    if(k==1)op=3;
    if(k==2)op=1;
    if(k==3)op=2;
    return op;
}
inline void add(int u,int v,int w,int c)
{
    e[++cnt_edge].nxt=head[u];
    head[u]=cnt_edge;
    e[cnt_edge].to=v;
    e[cnt_edge].flow=w;
    e[cnt_edge].cost=c;
}
inline void addflow(int u,int v,int w,int c)
{
    if(!col[u]&&u!=S&&v!=T)swap(u,v);//edge:: black->white.
    add(u,v,w,c);add(v,u,0,-c);
}
inline void solve(int x,int y,int type)
{
    if(!type||type==5||type==10||type==15)return;
    int num=0;
    for(int i=0;i<4;i++)if((type>>i)&1)num++;
    if(num==1)
    {
        if(type==1)
        {
            re int turn=0;
            addflow(id[x][y][turn],id[x][y][3],1,1);
            addflow(id[x][y][turn],id[x][y][2],1,1);
            addflow(id[x][y][turn],id[x][y][1],1,2);
            return;
        }
        if(type==2)
        {
            re int turn=3;
            addflow(id[x][y][turn],id[x][y][1],1,1);
            addflow(id[x][y][turn],id[x][y][0],1,1);
            addflow(id[x][y][turn],id[x][y][2],1,2);
            return;
        }
        if(type==4)
        {
            re int turn=1;
            addflow(id[x][y][turn],id[x][y][2],1,1);
            addflow(id[x][y][turn],id[x][y][3],1,1);
            addflow(id[x][y][turn],id[x][y][0],1,2);
            return;
        }
        if(type==8)
        {
            re int turn=2;
            addflow(id[x][y][turn],id[x][y][0],1,1);
            addflow(id[x][y][turn],id[x][y][1],1,1);
            addflow(id[x][y][turn],id[x][y][3],1,2);
            return;
        }
    }
    if(num==2)
    {
        if(type==3)
        {
            addflow(id[x][y][0],id[x][y][1],1,1);
            addflow(id[x][y][3],id[x][y][2],1,1);
            return;
        }
        if(type==6)
        {
            addflow(id[x][y][3],id[x][y][2],1,1);
            addflow(id[x][y][1],id[x][y][0],1,1);
            return;
        }
        if(type==9)
        {
            addflow(id[x][y][2],id[x][y][3],1,1);
            addflow(id[x][y][0],id[x][y][1],1,1);
            return;
        }
        if(type==12)
        {
            addflow(id[x][y][1],id[x][y][0],1,1);
            addflow(id[x][y][2],id[x][y][3],1,1);
            return;
        }
    }
    if(num==3)
    {
        if(type==7)
        {
            addflow(id[x][y][0],id[x][y][2],1,1);
            addflow(id[x][y][1],id[x][y][2],1,1);
            addflow(id[x][y][3],id[x][y][2],1,2);
            return;
        }
        if(type==11)
        {
            addflow(id[x][y][2],id[x][y][1],1,1);
            addflow(id[x][y][3],id[x][y][1],1,1);
            addflow(id[x][y][0],id[x][y][1],1,2);
            return;
        }
        if(type==13)
        {
            addflow(id[x][y][1],id[x][y][3],1,1);
            addflow(id[x][y][0],id[x][y][3],1,1);
            addflow(id[x][y][2],id[x][y][3],1,2);
            return;
        }
        if(type==14)
        {
            addflow(id[x][y][3],id[x][y][0],1,1);
            addflow(id[x][y][2],id[x][y][0],1,1);
            addflow(id[x][y][1],id[x][y][0],1,2);
            return;
        }
    }
}
inline bool spfa()
{
    memset(vis,0,sizeof(vis));
    memset(dis,0x3f,sizeof(dis));
    deque<int>q;
    q.push_front(S);dis[S]=0;vis[S]=1;
    while(!q.empty())
    {
        re int x=q.front();q.pop_front();vis[x]=0;
        for(re int i=head[x];i;i=e[i].nxt)
        {
            re int y=e[i].to;
            if(dis[y]>dis[x]+e[i].cost&&e[i].flow>0)
            {
                dis[y]=dis[x]+e[i].cost;
                if(!vis[y])
                {
                    if(q.empty()||dis[y]>dis[q.front()])q.push_back(y);
                    else q.push_front(y);
                    vis[y]=1;
                }
            }
        }
    }
    return dis[T]!=0x3f3f3f3f;
}
int dfs(int x,int lim)
{
    vis[x]=1;
    if(x==T||lim<=0)return lim;
    re int res=lim;
    for(re int i=head[x];i;i=e[i].nxt)
    {
        re int y=e[i].to;
        if(dis[y]!=dis[x]+e[i].cost||e[i].flow<=0||vis[y])continue;
        re int tmp=dfs(y,min(res,e[i].flow));
        res-=tmp;
        e[i].flow-=tmp,e[i^1].flow+=tmp;
        if(res<=0)break;
    }
    return lim-res;
}
inline pii Dinic()
{
    re int res=0,cost=0;
    while(spfa())
    {
        re int flow=dfs(S,inf);
        while(flow>0)
        {
            res+=flow,cost+=flow*dis[T];
            memset(vis,0,sizeof(vis));
            flow=dfs(S,inf);
        }
    }
    return mkp(res,cost);
}
int main()
{
    n=read(),m=read();
    for(re int i=1;i<=n;i++)
        for(re int j=1;j<=m;j++)
            a[i][j]=read();
    S=1;
    for(re int i=1;i<=n;i++)
        for(re int j=1;j<=m;j++)
            for(re int k=0;k<4;k++)
            {
                id[i][j][k]=++tot;
                col[tot]=!((i+j)&1);
            }
    T=tot+1;
    for(re int i=1;i<=n;i++)
        for(re int j=1;j<=m;j++)
            for(re int k=0;k<4;k++)
            {   
                if(!((a[i][j]>>k)&1))continue;
                sum++;
                re int op=change(k);
                if(!((i+j)&1))addflow(S,id[i][j][op],1,0);
                else addflow(id[i][j][op],T,1,0);
            }
    for(re int i=1;i<=n;i++)
        for(re int j=1;j<=m;j++)
        {
            if(i<n)addflow(id[i][j][1],id[i+1][j][0],1,0);
            if(j<m)addflow(id[i][j][3],id[i][j+1][2],1,0);
        }
    for(re int i=1;i<=n;i++)
        for(re int j=1;j<=m;j++)
            solve(i,j,a[i][j]);
    pii ans=Dinic();
    printf("%d",ans.fir==(sum>>1)?ans.sec:-1);
    return 0;
}

Guess you like

Origin www.cnblogs.com/nofind/p/12111701.html