[SDOI2012]象棋

题解:

sd的题目也真是奇怪

第一题有了最短路第二题还有

第二题有了网络流第三题还有

显然是可以网络流的

但考虑每个点只能存在一个这个条件

刚开始我以为是建分层图。。但发现这个时间复杂度太高了

其实我们考虑当两个人到一个点的时候可以交换速度(常用思想)

所以如果有解那么这个条件就是没有用的

所以也就是说这个条件是没有用的

那就变成了二分图最大权匹配

代码:

#include <bits/stdc++.h>
#define N 40000
#define maxn 500000
using namespace std;
struct re{
    int a,b,c,from,flow,cost;
}a[maxn];
struct ree{
    int a,b,c;
}e[maxn];
int l2,l,head[N],head2[N];
void arr(int x,int y,int z,int flow,int cost)
{
    a[++l].a=head[x];
    a[l].b=y;
    a[l].c=z;
    a[l].flow=flow;
    a[l].cost=cost;
    a[l].from=x;
    head[x]=l;
}
#define INF 1e9
int sum,d[N],s,t,p[N],aa[N],n,m;
bool inq[N];
bool bellmanford(int &flow,int &cost)
{
    for (int i=1;i<=sum;i++) d[i]=INF;
    memset(inq,0,sizeof(inq));
    d[s]=0; inq[s]=1; aa[s]=INF;
    queue<int>q;
    q.push(s);
    while (!q.empty())
    {
        int x=q.front(); q.pop();
        int u=head[x];
        while (u)
        {
            int v=a[u].b;
            if (a[u].c>a[u].flow&&d[v]>d[x]+a[u].cost)
            {
              d[v]=d[x]+a[u].cost;
              p[v]=u;
              aa[v]=min(aa[x],a[u].c-a[u].flow);
              if (!inq[v])
              {
                  q.push(v); inq[v]=1;
              }
            }
            u=a[u].a;
        }
        inq[x]=0;
    }
    if (d[t]==INF) return(0);
    flow+=aa[t];
    cost+=d[t]*aa[t];
    int x=t;
    while (x!=s)
    {
        int u=p[x];
        a[u].flow+=aa[t];
        if (u%2) a[u+1].flow-=aa[t]; else a[u-1].flow-=aa[t];
        x=a[u].from;
    }
    return 1;
}
int flow,cost;
void mincost()
{
    while (bellmanford(flow,cost));
}
int dx[5]={0,1,1,-1,-1};
int dy[5]={0,1,-1,1,-1};
queue<int> q;
bool ff[1000][1000];
char cc[N];
int js(int x,int y)
{
    return((x-1)*m+y);
}
bool pd(int x,int y)
{
    if (x>=1&&x<=n&&y>=1&&y<=m&&!ff[x][y]) return(1);
    else return(0);
}
void arr2(int x,int y)
{
    e[++l2].a=head2[x];
    e[l2].b=y;
    head2[x]=l2;
}
int k,a1,b1;
int x1[N],x2[N],y3[N],y4[N],dis[N];
bool vis[N];
int main()
{
  freopen("noi.in","r",stdin);
  freopen("noi.out","w",stdout);
    std::ios::sync_with_stdio(false);
    cin>>n>>m>>k>>a1>>b1;
    for (int i=1;i<=n;i++)
    {
        cin>>cc;
        int len=strlen(cc);
        for (int j=0;j<len;j++)
          if (cc[j]=='*') ff[i][j+1]=1;
    }
    for (int i=1;i<=k;i++)
      cin>>x1[i]>>y3[i];
    for (int i=1;i<=k;i++)
      cin>>x2[i]>>y4[i];
    for (int i=1;i<=n;i++)
      for (int j=1;j<=m;j++)
      if (pd(i,j))
      {
          for (int i1=1;i1<=4;i1++)
          {
            if (pd(i+dx[i1]*a1,j+dy[i1]*b1))
            {
                int k1=js(i,j);
                int k2=js(i+dx[i1]*a1,j+dy[i1]*b1);
                arr2(k1,k2);
          }
          if (pd(i+dx[i1]*b1,j+dy[i1]*a1))
          {
              int k1=js(i,j);
              int k2=js(i+dx[i1]*b1,j+dy[i1]*a1);
              arr2(k1,k2);
          }
        }
      }
    sum=2*k+1;
    for (int i=1;i<=k;i++)
    {
        int ax1=js(x1[i],y3[i]);
        for (int j=1;j<=n*m;j++)
          dis[j]=INF;
        memset(vis,0,sizeof(vis));
        dis[ax1]=0; q.push(ax1); vis[ax1]=1;
        while (!q.empty())
        {
            int x2=q.front(); q.pop();
            int u=head2[x2];
            while (u)
            {
                int v=e[u].b;
                if (!vis[v])
                {
                    
                  dis[v]=dis[x2]+1;
                  q.push(v);
                  vis[v]=1;
                }
                u=e[u].a;
            }
        }
        for (int j=1;j<=k;j++)
        {
            int ax2=js(x2[j],y4[j]);
            arr(i,j+k,1,0,dis[ax2]);
            arr(j+k,i,0,0,-dis[ax2]);
        }
    }
    s=0; t=2*k+1;
    for (int i=1;i<=k;i++)
    {
        arr(s,i,1,0,0); arr(i,s,0,0,0);
        arr(i+k,t,1,0,0); arr(t,i+k,0,0,0);
    }
    mincost();
    cout<<cost;
    return 0;
}
原文地址:https://www.cnblogs.com/yinwuxiao/p/8823106.html