POJ 2594 Treasure Exploration【传递闭包+最小路径覆盖】

大意:

有n个点,告诉你一些单向边,问多少条边能把所有的点覆盖【注意点能重复覆盖  比如4->1->2   5->3】

分析:

知识储备:

传递闭包:  所谓传递,可以这么理解,对于节点j如果i能到k并且k能到j那么i能到j,这样用像floyed就能处理出任意两个点能否到达

for(int k = 1; k <= n; k++) {
    for(int i = 1; i <= n; i++) {
        if(W[i][k]) {
            for(int j = 1; j <= n; j++) {
                W[i][j] = W[i][j] || (W[i][k] && W[k][j]);
            }
        }
    }
}

由于点可以被重复利用所以用传递闭包处理处任意两点的到达关系

在求最小路径覆盖就可以了。

代码:

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <vector>
 5 using namespace std;
 6
 7 const int maxn = 505;
 8 const int INF = 1000000000;
 9
10 int n;
11 int vis[maxn];
12 int Link[maxn];
13 vector<int> G[maxn];
14 bool Find(int u) {
15     for(int i = 0; i < G[u].size(); i++) {
16         int v = G[u][i];
17         if(!vis[v]) {
18             vis[v] = 1;
19             if(Link[v] == -1 || Find(Link[v])) {
20                 Link[v] = u;
21                 return true;
22             }
23         }
24     }
25     return false;
26 }
27
28 int solve() {
29     memset(Link, -1, sizeof(Link));
30     int cnt = 0;
31     for(int i = 1; i <= n; i++) {
32         if(G[i].size()) {
33             memset(vis, 0, sizeof(vis));
34             if(Find(i)) cnt++;
35         }
36     }
37     return cnt;
38 }
39
40 int W[maxn][maxn];
41 int main() {
42     int m;
43     int a, b;
44     while(scanf("%d %d",&n, &m) && ( n + m) ) {
45         for(int i = 1; i <= n; i++) G[i].clear();
46         memset(W, 0, sizeof(W));
47         while(m--) {
48             scanf("%d %d",&a, &b);
49             W[a][b] = 1;
50         }
51         for(int k = 1; k <= n; k++) {
52             for(int i = 1; i <= n; i++) {
53                 if(W[i][k]) {
54                     for(int j = 1; j <= n; j++) {
55                         W[i][j] = W[i][j] || (W[i][k] && W[k][j]);
56                     }
57                 }
58             }
59         }
60         for(int i = 1; i <= n; i++) {
61             for(int j = 1; j <= n; j++) {
62                 if(W[i][j]) G[i].push_back(j);
63             }
64         }
65         printf("%d\n",n - solve());
66     }
67     return 0;
68 }

时间: 2024-10-25 19:17:21

POJ 2594 Treasure Exploration【传递闭包+最小路径覆盖】的相关文章

POJ 2594 Treasure Exploration(最小路径覆盖变形)

POJ 2594 Treasure Exploration 题目链接 题意:有向无环图,求最少多少条路径能够覆盖整个图,点能够反复走 思路:和普通的最小路径覆盖不同的是,点能够反复走,那么事实上仅仅要在多一步.利用floyd求出传递闭包.然后依据这个新的图去做最小路径覆盖就可以 代码: #include <cstdio> #include <cstring> #include <vector> #include <algorithm> using names

POJ 2594 —— Treasure Exploration——————【最小路径覆盖、可重点、floyd传递闭包】

Treasure Exploration Time Limit:6000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u Submit Status Practice POJ 2594 Description Have you ever read any book about treasure exploration? Have you ever see any film about treasure exploratio

poj 2594 Treasure Exploration(最小路径覆盖/二分最大匹配)

Treasure Exploration Time Limit: 6000MS   Memory Limit: 65536K Total Submissions: 7208   Accepted: 2944 Description Have you ever read any book about treasure exploration? Have you ever see any film about treasure exploration? Have you ever explored

poj 2594 Treasure Exploration(最小路径覆盖,可重点)

题意:选出最小路径覆盖图中所有点,路径可以交叉,也就是允许路径有重复的点. 分析:这个题的难点在于如何解决有重复点的问题-方法就是使用Floyd求闭包,就是把间接相连的点直接连上边,然后就是求最小路径覆盖了.我来大概解释一下为什么是对的,首先我们要明确,当我们重复利用一个点的时候,一定是有两个比较良好的路径相交了,而二分图是不允许这样的情况存在的,因为那必然存在了一个点有一个以上的出度或者入度了,而怎么避免这个问题呢,看下面的图: 这就是针对这个问题的一个典型的模型,如果使用正常二分图,求得的匹

POJ2594 Treasure Exploration(最小路径覆盖+传递闭包)

题意: 派机器人去火星寻宝,给出一个无环的有向图,机器人可以降落在任何一个点上, 再沿着路去其他点探索,我们的任务是计算至少派多少机器人就可以访问到所有的点.点可以重复去. 思路: 最小路径覆盖,只是点可以重复去,就需要求传递闭包,用floyd /* *********************************************** Author :devil Created Time :2016/5/17 16:45:13 *****************************

Poj 2594 Treasure Exploration (最小边覆盖+传递闭包)

题目链接: Poj 2594 Treasure Exploration 题目描述: 在外星上有n个点需要机器人去探险,有m条单向路径.问至少需要几个机器人才能遍历完所有的点,一个点可以被多个机器人经过. 解题思路: 一眼看上去是普通的最小边覆盖,但是仔细想后发现如果在原图上进行最大匹配的话,每个点只能经过一次.这样的话对于本题求出的并不是最优解,所以我们要先对原图进行传递闭包处理,然后再进行最大匹配. 这个题目点数太少H_K和匈牙利算法在空间和时间上并没有什么差,就代码复杂度而言匈牙利算法更有优

poj 2594 Treasure Exploration (二分匹配)

Treasure Exploration Time Limit: 6000MS   Memory Limit: 65536K Total Submissions: 6558   Accepted: 2644 Description Have you ever read any book about treasure exploration? Have you ever see any film about treasure exploration? Have you ever explored

POJ 2594 Treasure Exploration(带交叉路的最小路径覆盖)

题意: 派机器人去火星寻宝,给出一个无环的有向图,机器人可以降落在任何一个点上,再沿着路去其他点探索,我们的任务是计算至少派多少机器人就可以访问到所有的点.有的点可以重复去. 输入数据: 首先是n和m, 代表有n个顶点, m条边.(m和n同时为0时则输入数据结束) 接下来m行,每行两个数字 a, b代表 从a到b可以通行. 题目分析: 这道题目与最小路径有一点差别,最小路径覆盖上是不存在交叉路的,但是这个题目是存在交叉路的. 对于交叉路的处理我们可以使用Floyd闭包传递.即 i->j, j->

POJ 2594 Treasure Exploration 最小可相交路径覆盖

最小路径覆盖 DAG的最小可相交路径覆盖: 算法:先用floyd求出原图的传递闭包,即如果a到b有路径,那么就加边a->b.然后就转化成了最小不相交路径覆盖问题. 这里解释一下floyd的作用如果1->2->3->4那么1可以到达2,3,4只要需要借助一些点,那么就可以直接把1与2,3,4相连,这就是floyd要做的事. 证明:为了连通两个点,某条路径可能经过其它路径的中间点.比如1->3->4,2->4->5.但是如果两个点a和b是连通的,只不过中间需要经