题意

给定一个有向图,在这个图上的某些点上放伞兵,可以使伞兵可以走到图上所有的点。且每个点只被一个伞兵走一次。问至少放多少伞兵。

思路

裸的最小路径覆盖。

°最小路径覆盖

【路径覆盖】在一个有向图G(V, E<u,v>)中,路径覆盖就是在图中找一些路经,使之覆盖了图中的所有顶点,且任何一个顶点有且只有一条路径与之关联(如果把这些路径中的每条路径从它的起始点走到它的终点,那么恰好可以经过图中的每个顶点一次且仅一次);如果不考虑图中存在回路,那么每条路径就是一个弱连通子集.

【最小路径覆盖】最小路径覆盖就是找出最小的路径条数,使之成为G的一个路径覆盖.

【解法 && 路径覆盖与二分图匹配的关系】最小路径覆盖=|V|-最大匹配数,其中最大匹配数的求法是把G中的每个顶点pi分成两个顶点pi'与pi'',如果在p中存在一条pi到pj的边,那么在二分图G'中就有一条连接pi'与pj''的无向边;这里pi' 就是p中pi的出边,pj''就是p中pj 的一条入边;

代码

[cpp]
#include
#include
#include
#include
#include
#include
#include
#define MID(x,y) ((x+y)/2)
#define MEM(a,b) memset(a,b,sizeof(a))
#define REP(i, begin, m) for (int i = begin; i < begin+m; i ++)
using namespace std;
const int MAXV = 1005; //N1+N2
vector adj[MAXV];
struct MaximumMatchingOfBipartiteGraph{
int vn;
void init(int n){ //二分图两点集点的个数
vn = n;
for (int i = 0; i <= vn; i ++) adj[i].clear();
}
void add_uedge(int u, int v){
adj[u].push_back(v);
adj[v].push_back(u);
}
bool vis[MAXV];
int mat[MAXV]; //记录已匹配点的对应点
bool cross_path(int u){
for (int i = 0; i < (int)adj[u].size(); i ++){
int v = adj[u][i];
if (!vis[v]){
vis[v] = true;
if (mat[v] == 0 || cross_path(mat[v])){
mat[v] = u;
mat[u] = v;
return true;
}
}
}
return false;
}
int hungary(){
MEM(mat, 0);
int match_num = 0;
for (int i = 1; i <= vn; i ++){
MEM(vis, 0);
if (!mat[i] && cross_path(i)){
match_num ++;
}
}
return match_num;
}
void print_edge(){
for (int i = 1; i <= vn; i ++){
for (int j = 0; j < (int)adj[i].size(); j ++){ printf("u = %d v = %d\n", i, adj[i][j]); } } } }match; struct rides{ int begintime, endtime; int x1, y1, x2, y2; }r[MAXV>>1];
int main(){
//freopen("test.in", "r", stdin);
//freopen("test.out", "w", stdout);
int t;
scanf("%d", &t);
while(t --){
int n;
scanf("%d", &n);
match.init(2*n);
REP(i, 0, n){
int hour, minute;
scanf("%d:%d %d %d %d %d", &hour, &minute, &r[i].x1, &r[i].y1, &r[i].x2, &r[i].y2);
r[i].begintime = hour * 60 + minute;
r[i].endtime = r[i].begintime + abs(r[i].x2 - r[i].x1) + abs(r[i].y2 - r[i].y1);
}
REP(i, 0, n) REP(j, 0, n){
if (i == j) continue;
if (abs(r[i].x2 - r[j].x1) + abs(r[i].y2 - r[j].y1) < (r[j].begintime - r[i].endtime)){
match.add_uedge(i, j+n);
}
}
printf("%d\n", n-match.hungary());
}
return 0;
}
[/cpp]

最新文章

  1. Oracle RAC安装部署文档
  2. iOS 开发笔记-AFNetWorking https SSL认证
  3. Monkey 使用aapt查看apk包名
  4. transform.localPosition操作时的一些注意事项
  5. 总结Selenium自动化测试方法(二)测试环境搭建
  6. 隐藏NavigationBar 带来的坑
  7. 关于video.js
  8. [转载] java多线程学习-java.util.concurrent详解(四) BlockingQueue
  9. python学习day3------列表、元组、字符串操作
  10. Redis分布式锁---完美实现
  11. install_driver(Oracle) failed: Can&#39;t load `.../DBD/Oracle/Oracle.so&#39; for module DBD::Oracle
  12. UNIX环境高级编程——可靠信号与不可靠信号
  13. string to int
  14. css 生成图片添加的十字
  15. js 事件模型详解
  16. 干货 | 揭秘如何增加listing多个类目节点
  17. [EXP]Jenkins 2.150.2 - Remote Command Execution (Metasploit)
  18. Aria2GUI 导出下载 刷新界面,任务消失
  19. 使用Gzip压缩数据,加快页面访问速度
  20. Xcode 5.0.1安装插件:规范注释生成器VVDocumenter + OSX 10.9.2

热门文章

  1. 安装wine qq2012
  2. POJ 3320
  3. java集合TreeMap应用---求一个字符串中,每一个字母出现的次数
  4. HDU 1116 || POJ 1386 || ZOJ 2016 Play on Words (欧拉回路+并查集)
  5. 李洪强iOS开发之【Objective-C】07-自定义构造方法和description方法
  6. servlet学习笔记三
  7. Girls: different perspectives to consider
  8. 阿里巴巴fastJson进行json数据解析
  9. Linux 关机命令详解
  10. VNC+SSH相关应用