P3355 骑士共存问题 二分建图 + 当前弧优化dinic

Posted ckxkexing

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P3355 骑士共存问题 二分建图 + 当前弧优化dinic相关的知识,希望对你有一定的参考价值。

P3355 骑士共存问题

题意:

  也是一个棋盘,规则是“马”不能相互打到。

思路:

  奇偶点分开,二分图建图,这道题要注意每个点可以跑八个方向,两边都可以跑,所以边 = 20 * n * n。

  然后dinic 要用当前弧优化。

技术图片
#include <algorithm>
#include  <iterator>
#include  <iostream>
#include   <cstring>
#include   <cstdlib>
#include   <iomanip>
#include    <bitset>
#include    <cctype>
#include    <cstdio>
#include    <string>
#include    <vector>
#include     <stack>
#include     <cmath>
#include     <queue>
#include      <list>
#include       <map>
#include       <set>
#include   <cassert>

using namespace std;
#define lson (l , mid , rt << 1)
#define rson (mid + 1 , r , rt << 1 | 1)
#define debug(x) cerr << #x << " = " << x << "
";
#define pb push_back
#define pq priority_queue



typedef long long ll;
typedef unsigned long long ull;
//typedef __int128 bll;
typedef pair<ll ,ll > pll;
typedef pair<int ,int > pii;
typedef pair<int,pii> p3;

//priority_queue<int> q;//这是一个大根堆q
//priority_queue<int,vector<int>,greater<int> >q;//这是一个小根堆q
#define fi first
#define se second
//#define endl ‘
‘

#define OKC ios::sync_with_stdio(false);cin.tie(0)
#define FT(A,B,C) for(int A=B;A <= C;++A)  //用来压行
#define REP(i , j , k)  for(int i = j ; i <  k ; ++i)
#define max3(a,b,c) max(max(a,b), c);
#define min3(a,b,c) min(min(a,b), c);
//priority_queue<int ,vector<int>, greater<int> >que;

const ll oo = 1ll<<17;
const ll mos = 0x7FFFFFFF;  //2147483647
const ll nmos = 0x80000000;  //-2147483648
const int inf = 0x3f3f3f3f;
const ll inff = 0x3f3f3f3f3f3f3f3f; //18
const int mod = 1000000007;
const double esp = 1e-8;
const double PI=acos(-1.0);
const double PHI=0.61803399;    //黄金分割点
const double tPHI=0.38196601;



template<typename T>
inline T read(T&x){
    x=0;int f=0;char ch=getchar();
    while (ch<0||ch>9) f|=(ch==-),ch=getchar();
    while (ch>=0&&ch<=9) x=x*10+ch-0,ch=getchar();
    return x=f?-x:x;
}
/*-----------------------showtime----------------------*/
            const int maxn = 209;
            int mp[maxn][maxn];

            struct E
            {
                int u,v,val;
                int nxt;                
            }edge[20 * maxn*maxn];
            int gtot = 0,head[maxn*maxn];
            void addedge(int u,int v,int val){
                edge[gtot].u = u;
                edge[gtot].v = v;
                edge[gtot].val = val;
                edge[gtot].nxt = head[u];
                head[u] = gtot++;

                edge[gtot].u = v;
                edge[gtot].v = u;
                edge[gtot].val = 0;
                edge[gtot].nxt = head[v];
                head[v] = gtot++;
            }
            int nx[8][2] = {
                {-2,-1}, {-1,-2},{-2, 1},{-1,2},{1,-2},{2,-1},{1,2},{2,1}
            };
            int n,m;
            int cal(int i,int j){
                return (i-1)*n + j;
            }

            int dis[maxn*maxn],cur[maxn*maxn];
            bool bfs(int s,int t){
                memset(dis, inf, sizeof(dis));
                for(int i=s; i<=t; i++) cur[i] = head[i];
                queue<int>que;
                que.push(s);
                dis[s] = 0;
                while(!que.empty()){
                    int u = que.front(); que.pop();
                    for(int i= head[u]; ~i; i = edge[i].nxt){
                        int v = edge[i].v;
                        if(edge[i].val > 0 && dis[v] > dis[u] + 1){
                            dis[v] = dis[u] + 1;
                            que.push(v);
                        }
                    }
                }
                return dis[t] < inf;
            }

            int dfs(int u,int t,int maxflow){
                if(u == t || maxflow == 0) return maxflow;

                for(int i=cur[u]; ~i; i = edge[i].nxt){
                    cur[u] = i;
                    int v = edge[i].v;
                    if(edge[i].val > 0 && dis[v] == dis[u] + 1){
                        int f = dfs(v, t, min(maxflow, edge[i].val));
                        
                        if(f > 0){
                            edge[i].val -= f;
                            edge[i^1].val += f;
                            return f;
                        }
                    }

                }
                return 0;
            }
            int dinic(int s,int t){
                int flow = 0;
                while(bfs(s,t)){
                    while(int f = dfs(s,t,inf)) flow += f;
                }
                return flow;
            }
int main(){
            memset(head, -1, sizeof(head));
            scanf("%d%d", &n, &m);
            int s = 0, t = n*n+1;
            int sum = n * n;
            for(int i=1; i<=m; i++){
                int x,y;
                scanf("%d%d", &x, &y);
                mp[x][y] = 1;
                sum--;
            }   
            for(int i=1; i<=n; i++){
                for(int j=1; j<=n; j++) {
                    if((i+j)% 2 == 1) {
                        if(mp[i][j]) addedge(s, cal(i,j), 0);
                        else addedge(s, cal(i, j), 1);
                    } 
                    else {
                        if(mp[i][j]) addedge(cal(i,j),t, 0);
                        else addedge(cal(i,j), t, 1);  
                    }
                }
            }

            for(int i=1; i<=n; i++){
                for(int j=1; j<=n; j++){
                        if((i+j)% 2 == 0) continue;
                        for(int k=0; k<8; k++){
                            int x = i + nx[k][0];
                            int y = j + nx[k][1];
                            if(x <1 || x > n || y < 1 || y > n) continue;
                            addedge(cal(i,j), cal(x,y),inf);
                        }
                }
            }
            cout<<sum - dinic(s, t)<<endl;
            return 0;
}
View Code

 

以上是关于P3355 骑士共存问题 二分建图 + 当前弧优化dinic的主要内容,如果未能解决你的问题,请参考以下文章

洛谷 [P3355] 骑士共存问题

luogu P3355 骑士共存问题

P3355 骑士共存问题最小点覆盖网络流24题

P3355 骑士共存问题 网络流

洛谷 P3355 骑士共存问题

洛谷 P3355 骑士共存问题最小割