[codevs 1922] 骑士共存问题

题解:

二分图最大独立集问题。

二分图的最大独立集:

选出一些点,让两两之间没有边相连。

二分图最大独立集问题一般转化为它的对偶问题——最小覆盖集,因为最大独立集要求每条边所连接的两个点最多有一个被选中,而最小覆盖集要求每条边所连接的两个点最少有一个被选中。那么点的个数-最小覆盖集点的个数=最大独立集(显然减掉的越少剩下的越多)。

那么最小覆盖怎么求呢?答案就是建立二分图求最大基数匹配。可以简单证明一下:

1)充分性:如果还有一条边没有被覆盖,那么此时一定可以把这条边作为一条新的匹配,说明此时还不是最大匹配。

2)必要性:如果可以删去一条边,二分图匹配边中是没有交点的,那么删去后这条边一定不会被覆盖。

算法就到此结束。

原题中记得要把总点数减去不能走的格子数。

代码:

dinic算法过了,ISAP死活不对...应该是我写的问题。
Dinic:

总时间耗费: 3172ms

总内存耗费: 11 kB

#include<cstdio>
#include<iostream>
#include<vector>
#include<cstring>
#include<string>
#include<queue>
#include<algorithm>
using namespace std;const int maxn = 200 * 200 + 10;
const int INF = 1e9 + 7;const int dx[] = {-1, -2, -2, -1, 1, 2, 2, 1};
const int dy[] = {-2, -1, 1, 2, 2, 1, -1, -2};int n, m, s, t;struct Edge {int from, to, cap, flow;
};vector<Edge> edges;
vector<int> G[maxn];void AddEdge(int from, int to, int cap) {edges.push_back((Edge){from, to, cap, 0});edges.push_back((Edge){to, from, 0, 0});int sz = edges.size();G[from].push_back(sz-2);G[to].push_back(sz-1);
}int id[222][222];
void init() {cin >> n >> m;s = 0; t = n*n - m + 1;for(int i = 0; i < m; i++) {int x, y;cin >> x >> y;id[x][y] = -1;}int c = 0;for(int i = 1; i <= n; i++)for(int j = 1; j <= n; j++)if(!id[i][j])  id[i][j] = ++c;for(int x = 1; x <= n; x++)for(int y = 1; y <= n; y++) if(id[x][y] > 0) {int ID = id[x][y];if((x+y)%2 == 0) {AddEdge(s, ID, 1);for(int i = 0; i < 8; i++) {int newx = x + dx[i], newy = y + dy[i];int newID = id[newx][newy];if(newx <= n && newy <= n && newx >= 1 && newy >= 1 && newID > 0) AddEdge(ID, newID, INF);}} else {AddEdge(ID, t, 1);}}
}bool vis[maxn];
int d[maxn];
bool BFS() {queue<int> Q;Q.push(s);memset(vis, 0, sizeof(vis));d[s] = 0;vis[s] = 1;while(!Q.empty()) {int u = Q.front(); Q.pop();for(int i = 0; i < G[u].size(); i++) {Edge& e = edges[G[u][i]];if(!vis[e.to] && e.cap > e.flow) {vis[e.to] = 1;d[e.to] = d[u] + 1;Q.push(e.to);}}}return vis[t];
}int cur[maxn];int DFS(int u, int a) {if(a == 0 || u == t) return a;int f, flow = 0;for(int& i = cur[u]; i < G[u].size(); i++) {Edge& e = edges[G[u][i]];if(d[u] + 1 == d[e.to] && (f = DFS(e.to, min(a, e.cap-e.flow))) > 0) {flow += f;e.flow += f;a -= f;edges[G[u][i]^1].flow -= f;if(a == 0) break;}}return flow;
}void Dinic() {int flow = 0;while(BFS()) {memset(cur, 0, sizeof(cur));flow += DFS(s, INF);}cout << n*n-m-flow << endl;
}int main() {init();Dinic();return 0;
}

ISAP:

TLE(哪错了呢?)

#include<cstdio>
#include<iostream>
#include<vector>
#include<queue>
#include<algorithm>
using namespace std;const int maxn = 200 * 200 + 10;
const int INF = 1e9 + 7;const int dx[] = {-1, -2, -2, -1, 1, 2, 2, 1};
const int dy[] = {-2, -1, 1, 2, 2, 1, -1, -2};int n, m, s, t;struct Edge {int from, to, cap, flow;
};vector<Edge> edges;
vector<int> G[maxn];void AddEdge(int from, int to, int cap) {edges.push_back((Edge){from, to, cap, 0});edges.push_back((Edge){to, from, 0, 0});int sz = edges.size();G[from].push_back(sz-2);G[to].push_back(sz-1);
}int id[222][222];
void init() {cin >> n >> m;s = 0; t = n*n - m + 1;for(int i = 0; i < m; i++) {int x, y;cin >> x >> y;id[x][y] = -1;}int c = 0;for(int i = 1; i <= n; i++)for(int j = 1; j <= n; j++)if(!id[i][j])  id[i][j] = ++c;for(int x = 1; x <= n; x++)for(int y = 1; y <= n; y++) if(id[x][y] > 0) {int ID = id[x][y];if((x+y)%2 == 0) {AddEdge(s, ID, 1);for(int i = 0; i < 8; i++) {int newx = x + dx[i], newy = y + dy[i];int newID = id[newx][newy];if(newx <= n && newy <= n && newx >= 1 && newy >= 1 && newID > 0) AddEdge(ID, newID, INF);}} else {AddEdge(ID, t, 1);}}
}bool vis[maxn];
int d[maxn], p[maxn], cur[maxn], num[maxn];int Augment() {int x = t, a = INF;while(x != 1) {Edge& e = edges[p[x]];a = min(a, e.cap-e.flow);x = e.from;}x = t;while(x != 1) {edges[p[x]].flow += a;edges[p[x]^1].flow -= a;x = edges[p[x]].from;}return a;
}void BFS() {queue<int> Q;bool vis[maxn];memset(vis, 0, sizeof(vis));d[t] = 0;Q.push(t);while(!Q.empty()) {int x = Q.front(); Q.pop();for(int i = 0; i < G[x].size(); i++) {Edge& e = edges[G[x][i]];if(e.cap == 0 && !vis[e.to]) {d[e.to] = d[x] + 1;vis[e.to] = 1;Q.push(e.to);}}}
} void Maxflow() {int flow = 0;BFS();memset(num, 0, sizeof(num));for(int i = 0; i <= t; i++) num[d[i]]++;int x = s;memset(cur, 0, sizeof(cur));while(d[s] < t) {if(x == t) {flow += Augment();x = s;}int ok = 0;for(int i = cur[x]; i < G[x].size(); i++) {Edge& e = edges[G[x][i]];if(e.cap > e.flow && d[x] == d[e.to] + 1) {ok = 1;p[e.to] = G[x][i];cur[x] = i;x = e.to;break;}}if(!ok) {int _m = t - 1;for(int i = 0; i < G[x].size(); i++) {Edge& e = edges[G[x][i]];if(e.cap > e.flow) _m = min(_m, d[e.to]);}if(--num[d[x]] == 0) break;num[d[x] = _m+1]++;cur[x] = 0;if(x != s) x = edges[p[x]].from;}}cout << n*n-m-flow << endl;
}int main() {init();Maxflow();return 0;
}

我的ISAP连草地排水都WA一个点。。。

dinic算法过了,ISAP死活不对...应该是我写的问题。
TLE

[codevs 1922] 骑士共存问题相关推荐

  1. 最小割 ---- 二分图最大独立集(集合冲突模型) ---- 骑士共存 方格取数(网络流24题)

    二分图独立集 定理: 二分图最大独立集=n - 二分图最大匹配 其实二分图独立集是特殊的一种最大权闭合子图.我们根据上文"收益"的思想,把选某个点的收益看为1,左部节点为正权点,右 ...

  2. 解题报告:X、骑士共存问题(最大独立集)(匈牙利 / 最大流)

    X.骑士共存问题(最大独立集)(匈牙利 / 最大流) 题目链接 [问题分析] 二分图最大独立集,转化为二分图最大匹配,从而用最大流解决. [建模方法] 首先把棋盘黑白染色,使相邻格子颜色不同.把所有可 ...

  3. loj #6226. 「网络流 24 题」骑士共存问题

    #6226. 「网络流 24 题」骑士共存问题 题目描述 在一个 n×n\text{n} \times \text{n}n×n 个方格的国际象棋棋盘上,马(骑士)可以攻击的棋盘方格如图所示.棋盘上某些 ...

  4. [COGS746] [网络流24题] 骑士共存

    ★★☆   输入文件:knight.in   输出文件:knight.out   简单对比 时间限制:1 s   内存限制:128 MB 骑士共存问题 «问题描述: 在一个n*n个方格的国际象棋棋盘上 ...

  5. P3355 骑士共存问题(网络流)

    P3355 骑士共存问题 经典的最大独立集问题,最大独立集就是最小点覆盖的补集,因为最小点覆盖等于最大匹配,所以最大独立集等于点数减去最大匹配.

  6. P3355 骑士共存问题

    P3355 骑士共存问题 题目描述 在一个 n*n (n <= 200)个方格的国际象棋棋盘上,马(骑士)可以攻击的棋盘方格如图所示.棋盘上某些方格设置了障碍,骑士不得进入 对于给定的 n*n ...

  7. 网络流建模方法(四)—— 互不攻击问题 洛谷 P3353 骑士共存问题 (附 洛谷 P2774 方格取数问题)

    网络流建模方法(四)互不攻击问题,或者说是共存问题, 这类题目看起来有点像二分图匹配,这类题目我们就是建一个二分图然后跑最大流 还是先说题目洛谷P3353 题目描述 在一个 nn个方格的国际象棋棋盘上 ...

  8. 洛谷P3355 骑士共存问题

    题目描述 在一个 n*n个方格的国际象棋棋盘上,马(骑士)可以攻击的棋盘方格如图所示.棋盘上某些方格设置了障碍,骑士不得进入 对于给定的 n*n 个方格的国际象棋棋盘和障碍标志,计算棋盘上最多可以放置 ...

  9. 洛谷 P3355 骑士共存问题

    题意:给你一个棋盘,然后有一个骑士rider,棋盘上有一些障碍,问你最多放多少个骑士 思路:期初我一直以为这种题是什么八皇后问题的变形,队友告诉我,这是网络流,由于这道题的黄色格子上的棋子的下一步总是 ...

最新文章

  1. 微信小程序实现滑动翻页效果源码附效果图
  2. Gson:我爸是 Google
  3. 数据结构——非线性结构
  4. 一篇文章带你了解https是如何做到客户端与服务端之间安全通信
  5. gradle的下载与环境变量配置
  6. 在spring boot中集成Swagger
  7. 【Demo】配置重试和超时策略
  8. Libra白皮书解读
  9. Android之JNI DETECTED ERROR IN APPLICATION: illegal class name ‘XXX‘的错误解决方法
  10. 安装翻译_百度翻译下载安装官方地址
  11. Spring中注解注入bean和配置文件注入bean
  12. 系统管理员最应该读的5本书_系统管理员的8本书
  13. 英国反垄断监管机构将对音乐流媒体市场展开调查
  14. 苹果多款产品加征关税至15% 目前售价暂无影响
  15. linux jzmq编译,Linux下ps aux解释
  16. 关于firefox火狐中localStorage无法正常使用的问题
  17. Lesson 3 上机练习题——继承
  18. 虚幻引擎C++开发学习(一)
  19. ns手柄pc驱动_颜值、功能、手感同步在线 北通宙斯机械游戏手柄体验
  20. 李若彤揭秘退隐10年原因:感情不顺 父亲离世 曾患抑郁症

热门文章

  1. [云炬创业基础笔记]第十章企业的利润计划测试8
  2. [云炬创业基础笔记]第七章创业资源测试3
  3. 专栏 | 基于 Jupyter 的特征工程手册:数据预处理(三)
  4. python3:module
  5. 一文读懂汇编程序的多个分段的程序--详解
  6. 【CyberSecurityLearning 70】DC系列之DC-1渗透测试(Drupal)
  7. 操作符offset 和 jmp指令
  8. SpringBoot 根据传参返回不同的内容
  9. 代码段间转移控制时的特权级检查(JMP/CALL)——《x86汇编语言:从实模式到保护模式》读书笔记28
  10. 【⚡小丑竟然是我自己⚡】安防三年,今天才知道什么是ONVIF