zoukankan      html  css  js  c++  java
  • [网络流24题] 骑士共存问题

    题面:

    传送门

    思路:

    基本上和方格取数问题差不多

    这道题可以证明,如果把每两个不能共存的点连在一起,那么这个图没有奇环,是一个二分图

    同时,如果把这个图像国际象棋一样黑白染色,那么连边的两个点颜色不同

    源点连黑点,边权为1

    黑点连白点,边权为inf

    白点连汇点,边权为1

    跑出最大流,即为这个图的最小点覆盖

    用整张图的点数减去障碍物数量,再减去最大流的值就是答案了

    Code:

     1     #include<iostream>
     2     #include<cstdio>
     3     #include<cstring>
     4     #include<queue>
     5     #define inf 0x7fffffff
     6     using namespace std;
     7     struct erickin{
     8         int to,next,data,rev;
     9     }edge[400010];
    10     const int dx[9]={0,-2,-2,-1,-1,1,1,2,2};
    11     const int dy[9]={0,1,-1,2,-2,2,-2,1,-1};
    12     int n,m=0,mm;bool a[210][210];
    13     int first[50010],d[50010];
    14     void add(int op,int ed,int val){
    15         ++m;edge[m].to=ed;edge[m].rev=m+1;edge[m].data=val;edge[m].next=first[op];first[op]=m;
    16         ++m;edge[m].to=op;edge[m].rev=m-1;edge[m].data=0;edge[m].next=first[ed];first[ed]=m;
    17     }
    18     int bfs(int s,int t){
    19         memset(d,-1,sizeof(d));
    20         queue<int>q;int u,v,p;
    21         d[s]=0;
    22         q.push(s);
    23         while(!q.empty()){
    24             u=q.front();p=first[u];q.pop();
    25     //        cout<<"in pt "<<u<<endl;
    26             while(p!=-1){
    27                 v=edge[p].to;
    28     //            cout<<"    going to pt "<<v<<endl;
    29                 if(d[v]<0&&edge[p].data>0){
    30     //                cout<<"        success!"<<endl;
    31                     d[v]=d[u]+1;
    32                     if(v==t) return 1;
    33                     q.push(v);
    34                 }
    35                 p=edge[p].next;
    36             }
    37         }
    38         return 0;
    39     }
    40     int dfs(int u,int flow,int ed){
    41         if(u==ed) return flow;
    42         int p=first[u],cur=0,v,t;
    43     //    cout<<"dfs in "<<u<<ends<<flow<<ends<<ed<<endl;
    44         while(p!=-1){
    45             v=edge[p].to;
    46     //        cout<<"     to "<<v<<endl;
    47             if(edge[p].data>0&&d[v]==d[u]+1&&(t=dfs(v,min(flow-cur,edge[p].data),ed))){
    48                 edge[p].data-=t;edge[edge[p].rev].data+=t;cur+=t;
    49                 if(cur==flow) return flow;
    50             }
    51             p=edge[p].next;
    52         }
    53         if(!cur) d[u]=-1;
    54         return cur;
    55     }
    56     void dinic(int s,int t){
    57         int ans=0;
    58         while(bfs(s,t)) ans+=dfs(s,inf,t);
    59         printf("%d",(((n*n)-mm)-ans));
    60     }
    61     int main(){
    62         freopen("knight.in","r",stdin);
    63         freopen("knight.out","w",stdout);
    64         memset(first,-1,sizeof(first));
    65         scanf("%d%d",&n,&mm);
    66         int x1,x2;
    67         for(int i=1;i<=mm;i++){
    68             scanf("%d%d",&x1,&x2);
    69             a[x1][x2]=1;
    70         }
    71         for(int i=1;i<=n;i++){
    72             for(int j=1;j<=n;j++){
    73                 if(a[i][j]) continue;
    74                 int now=n*(i-1)+j;
    75                 if((i+j)%2){
    76                     add(0,now,1);
    77                     for(int k=1;k<=8;k++){
    78                         int ti=i+dx[k],tj=j+dy[k];
    79                         if(!a[ti][tj]&&0<ti&&ti<=n&&0<tj&&tj<=n){
    80                             int now1=n*(ti-1)+tj;
    81                             add(now,now1,inf);
    82                         }
    83                     }
    84                 }
    85                 else add(now,n*n+1,1);
    86             }
    87         }
    88         dinic(0,n*n+1);
    89     } 
  • 相关阅读:
    ExtJS学习之路第一步:对比jQuery,认识ExtJS
    创建Windows服务(C++)
    吴恩达2014机器学习教程笔记目录
    在Hexo中渲染MathJax数学公式
    Linux服务器性能检测命令集锦
    Redis开启AOF导致的删库事件
    从表扩展增加列属性说起
    数据库规约解读
    MySQL规约(阿里巴巴)
    HDFS运行原理
  • 原文地址:https://www.cnblogs.com/dedicatus545/p/8454427.html
Copyright © 2011-2022 走看看