[网络流24题] 骑士共存问题

神仙建图...

最多可以放上几个,也就是全都放上去之后尽量少删掉几个。

发现马总是会由同色攻击至异色,于是将两点之间连边,最后一定是一个二分图。

最后删掉的就是二分图的最小割,也就是最大匹配。

然后随便固定一个顺序,建立源点s以及汇点t,然后就跟普通二分图匹配的做法一样了。

  1 #include <bits/stdc++.h>
  2 #define dbg(x) cout << #x " = " << x << "\n"
  3 #define mp make_pair
  4 #define y0 lkhklhhkukgasdxcsasdwre
  5 #define y1 ajsodihousejbkrjykuasyi
  6 #define rep(i , x , y) for(int (i)=(x);(i)<=(y);++i)
  7 #define per(i , y , x) for(int (i)=(y);(i)>=(x);--i)
  8 #define FORALL(i) for(int i = head[u]; i != -1; i = e[i] . nxt)
  9 #define FORALLV(i , v) for(int i = 0; i < v . size(); ++i)
 10 /*********************
 11   Template : LiM_817
 12 *********************/
 13 using namespace std;
 14 typedef long long ll;
 15 typedef unsigned long long ull;
 16 typedef long double ld;
 17 typedef pair <int , int> pii;
 18 typedef pair <ll , ll> pll;
 19 inline int read() {
 20     int f = 1 , x = 0; char ch = getchar();
 21     while(ch < '0' || ch > '9') {if(ch == '-') f = -1;ch = getchar();}
 22     while(ch >= '0' && ch <= '9') {x = x * 10 + ch - '0'; ch = getchar();};
 23     return f * x;
 24 }
 25 template <typename T>
 26 inline void print(T x) {
 27     if(x < 0) putchar('-') , x = -x;
 28     if(x >= 10) print(x / 10); putchar(x % 10 + 48);
 29 }
 30 
 31 const int maxe = 500000 + 10;
 32 const int maxn = 500 + 10;
 33 const int maxs = 50000 + 10;
 34 const int dx[8] = {2 , 2 , 1 , 1 , -1 , -1 , -2 , -2};
 35 const int dy[8] = {-1 , 1 , -2 , 2 , -2 , 2 , -1 , 1};
 36 struct Edge {
 37     int v , w , nxt , flow;
 38 }e[maxe];
 39 int n , m , s , t;
 40 int color[maxn][maxn] , md[maxn][maxn];
 41 int head[maxs] , gg[maxs] , d[maxs];
 42 int Edgecnt = 0;
 43 void Link(int u , int v , int w) {
 44     e[Edgecnt] = (Edge){v , w , head[u] , 0} , head[u] = Edgecnt++;
 45     e[Edgecnt] = (Edge){u , 0 , head[v] , 0} , head[v] = Edgecnt++;
 46 }
 47 
 48 bool bfs() {
 49     queue <int> q;
 50     //while(!q . empty()) q . pop();
 51     memset(d , 0 , sizeof(d));
 52     memcpy(gg , head , sizeof(head));
 53     d[s] = 1;
 54     q . push(s);
 55     while(!q . empty()) {
 56         int u = q . front(); q . pop();
 57         //cout << u <<  " ";
 58         for(int i = head[u]; i != -1; i = e[i] . nxt) {
 59             int v = e[i] . v , w = e[i] . w , flow = e[i] . flow;
 60             if(!d[v] && w > flow) {
 61                 d[v] = d[u] + 1;
 62                 q . push(v);
 63                 if(v == t) return 1;
 64             }
 65         }
 66     }
 67     return 0;
 68 }
 69 
 70 int dfs(int u , int cap) {
 71     if(u == t) return cap;
 72     int outcap = 0;
 73     //cout << u << endl;
 74     for(int i = gg[u]; i != -1 && outcap < cap; i = e[i] . nxt) {
 75         gg[u] = i;
 76         int v = e[i] . v , w = e[i] . w , flow = e[i] . flow;
 77         if(d[v] == d[u] + 1 && w > flow) {
 78             int tmpcap = dfs(v , min(cap - outcap , w - flow));
 79             outcap += tmpcap;
 80             e[i] . flow += tmpcap;
 81             e[i ^ 1] . flow -= tmpcap;
 82         }
 83     }
 84     return outcap;
 85 }
 86 
 87 int MinCut() {
 88     int MaxFlow = 0;
 89     while(bfs()) MaxFlow += dfs(s , 0x3f3f3f3f); 
 90     return MaxFlow;
 91 }
 92 
 93 int main() {
 94     memset(head,  -1 , sizeof(head));
 95     memset(gg , -1 , sizeof(gg));
 96     n = read() , m = read();
 97     
 98     for(int i = 1;i <= m;i++)   {
 99         int u = read() , v = read();
100         color[u][v] = 1;
101     } 
102     
103     int cnt = 0;
104     for(int i = 1; i <= n; i++)
105         for(int j = 1; j<= n; j++)
106             if(!color[i][j]) md[i][j] = ++cnt;
107     s = 0 , t = cnt + 1;
108     
109     for(int i = 1; i <= n; i++)
110         for(int j = 1; j <= n; j++) {
111             if(color[i][j]) continue;
112             if((i + j) % 2) Link(md[i][j] , t , 1);
113             else Link(s , md[i][j] , 1);
114         }
115     //cout << "DBG1\n";
116     for(int i = 1; i <= n; i++) {
117         for(int j = 1; j <= n; j++) {
118             if(color[i][j]) continue;
119             if((i + j) % 2) continue;
120             for(int op = 0; op < 8; op++) {
121                 int x = i + dx[op] , y = j + dy[op];
122                 if(x < 1 || x > n || y < 1 || y > n) continue;
123                 if(color[x][y] != 2 && color[i][j] == 0) Link(md[i][j] , md[x][y] , 0x3f3f3f3f);
124             }
125         } 
126     }
127     //cout << "DBG2\n";
128 //    cout << "DBG3\n";
129     cout << n * n - m - MinCut();
130     return 0;
131 }
132 
133 // make sure about ll and int!!!

猜你喜欢

转载自www.cnblogs.com/LiM-817/p/10122429.html
今日推荐