poj 2594 Treasure Exploration(可重点最小路径覆盖)(二分匹配+Floyd求传递闭包)
2016-02-26 17:10
495 查看
题意:不是赤裸裸的最小路径覆盖(走遍所有的点),正常的最小路径覆盖中两个人走的路径不能有重复的点,而本题可以重复。
分析:我们仍可将问题转化为最小路径覆盖。如果一个人需要经过另一个人走过的点的时候,让他直接从该点上空飞过去,越过该点,直接走下一个点。如果我们赋予每个人这种能力,那么求得的无重复点的最小路径覆盖结果,就是题目要求的结果,因为需要重复的地方只要飞过去,就可以不重复了。赋予这个能力的方法就是把所有点能间接到达的点全都改为直接到达。然后正常求最小路径覆盖即可。
分析:我们仍可将问题转化为最小路径覆盖。如果一个人需要经过另一个人走过的点的时候,让他直接从该点上空飞过去,越过该点,直接走下一个点。如果我们赋予每个人这种能力,那么求得的无重复点的最小路径覆盖结果,就是题目要求的结果,因为需要重复的地方只要飞过去,就可以不重复了。赋予这个能力的方法就是把所有点能间接到达的点全都改为直接到达。然后正常求最小路径覆盖即可。
#include <iostream> #include <cstdio> #include <iostream> #include <cstring> #include <string> #include <cstdlib> #include <algorithm> #include <cmath> using namespace std; const int MAX=510; int map[MAX][MAX]; //图 int vis[MAX]; //访问标志 int match[MAX]; //匹配数组 int N,M; //N:顶点数 M:边数 bool Dfs(int u) //判断顶点u是否可以找到可匹配的顶点 { for (int v=1;v<=N;v++) { if (!vis[v] && map[u][v]) { vis[v]=1; if (match[v]==0 || Dfs(match[v])) { match[v]=u; return true; } } } return false; } void Floyd() //传递闭包:建新图 { for (int k=1;k<=N;k++) { for (int i=1;i<=N;i++) { for (int j=1;j<=N;j++) { if (map[i][k] && map[k][j]) //顶点i和顶点j可到达 { map[i][j]=1; } } } } } int main() { int i; int x,y; while (scanf("%d%d",&N,&M) && (N | M)) { memset(map,0,sizeof(map)); memset(match,0,sizeof(match)); //输入边 for (i=1;i<=M;i++) { scanf("%d%d",&x,&y); map[x][y]=1; } //建新图 Floyd(); //求最大匹配 int sum=0; for (i=1;i<=N;i++) { memset(vis,0,sizeof(vis)); if (Dfs(i)) { sum++; } } printf("%d\n",N-sum); //输出最小路径覆盖 } return 0; }
相关文章推荐
- inline函数
- Python中正则表达式的一些匹配规则
- 代码review发现问题 笔记201601
- httpmodule初识
- 我们为什么要用fitsSystemWindows?
- iPhone像素点和常用控件尺寸
- GitHub 优秀的 Android 开源项目
- Objective-C页面跳转方法总结
- grunt-watch插件的使用
- uva10465 完全背包
- mac mongodb 操作
- 【Web API系列教程】3.2 — 实战:处理数据(添加模型和控制器)
- 基于RMI服务传输大文件的完整解决方案
- CentOS 6.5 64位,调整分区大小
- angular.injector
- iOS开发调试篇—Print Description of "string"
- JSON串(字典、数组)转化为字符串
- java读取xls表格数据
- Redis学习--事务
- mysql数据库常用的时间函数