[网络流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     } 

 

posted @ 2018-02-19 21:05  dedicatus545  阅读(149)  评论(0编辑  收藏  举报