FTR #1 百步穿杨

一定要纪念这一天。

我这题调了整整一天。。。。。

2333

大概错了一个小地方,然后是两个建图的错误。

一是拆点,二是inf的是单向边。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#define maxn 55
#define maxv 100050
#define maxe 10000050
#define inf 1000000007
using namespace std;
int n,m,map[maxn][maxn],dis[maxv],nume=1,g[maxv],tot=0,lab[maxn][maxn],tab[maxv],max_flow=0;
int stack[maxv],top=0,s,t,cnt=0;
int s1[maxv],s2[maxv],t1=0,t2=0,cnts[maxn][maxn];
bool vis[maxn*maxn][maxn][maxn];
struct edge
{
    int v,f,nxt;
}e[maxe];
struct point
{
    int x,y,d;
    point (int x,int y,int d):x(x),y(y),d(d) {}
    point () {}
}p[maxv],en[maxv];
queue <int> q;
int dx[]={0,-1,1,0,0},dy[]={0,0,0,-1,1};
char ss[maxn];
void addedge(int u,int v,int f)
{
    e[++nume].v=v;e[nume].f=f;
    e[nume].nxt=g[u];g[u]=nume;
    e[++nume].v=u;e[nume].f=0;
    e[nume].nxt=g[v];g[v]=nume;
}
bool judge(int x,int y)
{
    return ((x>=1) && (x<=n) && (y>=1) && (y<=m) && (map[x][y]>=0));
}
void build(int xx)
{
    top=0;
    int x=p[xx].x,y=p[xx].y,d=p[xx].d,mx=0;
    if (d<=2) stack[++top]=s;else stack[++top]=t;
    if (judge(x+dx[d],y+dy[d]))
    {
        do
        {
            x+=dx[d];y+=dy[d];
            if (map[x][y]>mx) {mx=map[x][y];stack[++top]=lab[x][y];en[xx]=point(x,y,0);vis[xx][x][y]=true;}
        }while (judge(x+dx[d],y+dy[d]));
        if (d<=2) for (int i=1;i<=top-1;i++) addedge(stack[i],stack[i+1],mx-tab[stack[i]]);
        else for (int i=1;i<=top-1;i++) addedge(stack[i+1]+cnt,stack[i]+cnt*(i!=1),mx-tab[stack[i]]);
        max_flow+=mx;
    }
}
void cross(int x,int y)
{
    if ((max(p[x].d,p[y].d)<=2) || (min(p[x].d,p[y].d)>=3)) return;
    t1=0;t2=0;int xx,yy,d,retx=-1,rety=-1,pp=-1,qq=-1;
    int ex1,ey1,ex2,ey2;
    xx=p[x].x;yy=p[x].y;d=p[x].d;
    if (judge(xx+dx[d],yy+dy[d]))
    {
        do 
        {
            xx+=dx[d];yy+=dy[d];
            cnts[xx][yy]++;
            if ((xx==en[x].x) && (yy==en[x].y)) break;
        }while (judge(xx+dx[d],yy+dy[d]));
    }
    ex1=xx;ey1=yy;
    xx=p[y].x;yy=p[y].y;d=p[y].d;
    if (judge(xx+dx[d],yy+dy[d]))
    {
        do
        {
            xx+=dx[d];yy+=dy[d];cnts[xx][yy]++;
            if (cnts[xx][yy]==2) retx=xx,rety=yy;
            if ((xx==en[y].x) && (yy==en[y].y)) break;
        }while (judge(xx+dx[d],yy+dy[d]));
    }
    ex2=xx;ey2=yy;
    int flag1=0,flag2=0;
    while ((ex1!=p[x].x) || (ey1!=p[x].y))
    {
        cnts[ex1][ey1]--;
        if ((map[ex1][ey1]) && (!flag1) && (retx!=-1) && (rety!=-1) && (vis[x][ex1][ey1])) pp=lab[ex1][ey1];
        if ((ex1==retx) && (ey1==rety)) flag1=1;
        ex1-=dx[p[x].d];ey1-=dy[p[x].d];
    }
    while ((ex2!=p[y].x) || (ey2!=p[y].y))
    {
        cnts[ex2][ey2]--;
        if ((map[ex2][ey2]) && (!flag2) && (retx!=-1) && (rety!=-1) && (vis[y][ex2][ey2])) qq=lab[ex2][ey2];
        if ((ex2==retx) && (ey2==rety)) flag2=1;
        ex2-=dx[p[y].d];ey2-=dy[p[y].d];
    }
    if ((pp==-1) || (qq==-1)) return;
    if (p[x].d>=3) swap(pp,qq);
    addedge(pp,qq+cnt,inf);
}
bool bfs()
{
    q.push(s);
    for (int i=s;i<=t;i++) dis[i]=inf;
    dis[s]=0;
    while (!q.empty())
    {
        int head=q.front();q.pop();
        for (int i=g[head];i;i=e[i].nxt)
        {
            int v=e[i].v;
            if ((e[i].f>0) && (dis[v]>dis[head]+1))
            {
                dis[v]=dis[head]+1;
                q.push(v);
            }
        }
    }
    return dis[t]!=inf;
}
int dinic(int x,int low)
{
    if (x==t) return low;
    int ret=0;
    for (int i=g[x];low && i;i=e[i].nxt)
    {
        int v=e[i].v;
        if (e[i].f>0 && dis[v]==dis[x]+1)
        {
            int dd=dinic(v,min(low,e[i].f));
            ret+=dd;low-=dd;
            e[i].f-=dd;e[i^1].f+=dd;
        }
    }
    if (!ret) dis[x]=inf;
    return ret;
}
int main()
{
    scanf("%d%d",&n,&m);
    for (int i=1;i<=n;i++)
    {
        scanf("%s",ss);
        for (int j=1;j<=m;j++)
        {
            if ((ss[j-1]>='0') && (ss[j-1]<='9')) map[i][j]=ss[j-1]-'0';
            else if (ss[j-1]=='.') map[i][j]=0;
            else
            {
                map[i][j]=-1;
                if (ss[j-1]=='A') p[++tot]=point(i,j,1);
                else if (ss[j-1]=='V') p[++tot]=point(i,j,2);
                else if (ss[j-1]=='<') p[++tot]=point(i,j,3);
                else p[++tot]=point(i,j,4);
            }
        }
    }
    for (int i=1;i<=n;i++)
        for (int j=1;j<=m;j++)
            if (map[i][j]>0) lab[i][j]=++cnt,tab[cnt]=map[i][j];
    s=0;t=2*cnt+1;
    for (int i=1;i<=tot;i++) build(i);
    for (int i=1;i<=tot;i++)
            for (int j=i+1;j<=tot;j++)
                cross(i,j);
    while (bfs())
            max_flow-=dinic(s,inf);
    printf("%d
",max_flow);
    return 0;
}
原文地址:https://www.cnblogs.com/ziliuziliu/p/6480601.html