• 长脖子鹿放置(最大流)


    题意还是很容易理解的  感觉同(骑士共存问题)

    主要就是建图了

    将棋盘进行染色,这次不同于骑士共存那道题,这次直接对第几行染色

    证明的话,自己yy了一个:

    因为每一行无法到达的只有相邻的两行,那么就可以分情况了

    若一行行数为奇数,那么将其与超级源点相连,流量为1

    反之亦然,于超级汇点相连,同理流量为1

    对于那些障碍点直接判掉就好了,

    这样的话跟上面一样,在遍历整个图同时将不同的点进行相连,流量为INF,表示一种相连关系

    最后愉快的跑一下最大流即可

    题面

    #include<bits/stdc++.h>
    using namespace std;
    const int N=1e6+7;
    const int INF=0x7f7f7f7f;
    int m,n,k,p,s,t,cnt=1,ans,tot;
    int dx[9]={0,-3,-3,-1,-1,1,1,3,3},dy[9]={0,-1,1,-3,3,-3,3,-1,1};
    struct node
    {
        int nx,to,flow;
    } e[N];
    int id(int x,int y) {return (x-1)*m+y;}
    int dep[N],head[N];
    void add_edge(int a,int b,int flow)
    {
        cnt++;e[cnt].flow=flow;e[cnt].nx=head[a];e[cnt].to=b;head[a]=cnt;
        cnt++;e[cnt].flow=0;e[cnt].nx=head[b];e[cnt].to=a;head[b]=cnt;
    }
    bool used[210][210];
    bool bfs(int s,int t)
    {
        queue<int> que;memset(dep,0,sizeof(dep));
        que.push(s);dep[s]=1;
        while (!que.empty())
        {
            int x=que.front();que.pop();
            for (int i=head[x];i;i=e[i].nx)
            {
                int y=e[i].to;
                if (dep[y]==0&&e[i].flow)
                {
                    dep[y]=dep[x]+1;
                    que.push(y);
                }
            }
        }
      if (dep[t]==0) return false;
      else return true;
    }
    int dfs(int x,int limit,int t)
    {
        if (x==t) return limit;
        int used=0;
        for (int i=head[x];i;i=e[i].nx)
        {
            int y=e[i].to;
            if (dep[y]==dep[x]+1&&e[i].flow>0)
            {
                int di=dfs(y,min(limit-used,e[i].flow),t);
                if (di>0)
                {
                    e[i].flow-=di;
                    e[i^1].flow+=di;
                    used+=di;
                    if (used==limit) return used;
                }
            }
        }
      if (!used) dep[x]=-2;
      return used;
    }
    void dinic(int s,int t)
    {
        while (bfs(s,t)) 
        {ans+=dfs(s,INF,t);
         tot++;}
    }
    int main()
    {
        scanf("%d%d%d",&n,&m,&p);
        s=N-3;t=N-4;
        for (int i=1;i<=p;i++)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            used[x][y]=true;
        }
        for (int i=1;i<=n;i++)
         for (int j=1;j<=m;j++)
        if (!used[i][j])
        {
            if (i%2==1) add_edge(s,id(i,j),1);
            else add_edge(id(i,j),t,1);
        }
        for (int i=1;i<=n;i++)
         for (int j=1;j<=m;j++)
         {
             if (i%2!=1) continue;
             for (int k=1;k<=8;k++)
             {
                 int x=i+dx[k],y=j+dy[k];
                 if (x<=0||y<=0||x>n||y>m) continue;
                 if (used[x][y]) continue;
                 add_edge(id(i,j),id(x,y),INF);
             }
         }
        dinic(s,t);
        printf("%d",n*m-ans-p);
        return 0; 
    }
    慢即是快,细则是能,于小处铸迤逦
  • 相关阅读:
    20155333 2016-2017-2 《Java程序设计》第十周学习总结
    实验二 面向对象程序设计
    20155333 2016-2017-2 《Java程序设计》第九周学习总结
    20155333 2016-2017-2 《Java程序设计》第八周学习总结
    总结
    家庭作业第三章
    20135316王剑桥 linux第六周课实验笔记
    20135316王剑桥 linux第五周课实验笔记
    20135316王剑桥 linux第四周课实验笔记
    20135316王剑桥 linux第三周课实验笔记
  • 原文地址:https://www.cnblogs.com/Hale522520/p/10630742.html
Copyright © 2020-2023  润新知