POJ 2594 传递闭包的最小路径覆盖

Treasure Exploration

Time Limit: 6000MS   Memory Limit: 65536K
Total Submissions: 7171   Accepted: 2930

Description

Have you ever read any book about treasure exploration? Have you ever see any film about treasure exploration? Have you ever explored treasure? If you never have such experiences, you would never know what fun treasure exploring brings to you. 
Recently, a company named EUC (Exploring the Unknown Company) plan to explore an unknown place on Mars, which is considered full of treasure. For fast development of technology and bad environment for human beings, EUC sends some robots to explore the treasure. 
To make it easy, we use a graph, which is formed by N points (these N points are numbered from 1 to N), to represent the places to be explored. And some points are connected by one-way road, which means that, through the road, a robot can only move from one end to the other end, but cannot move back. For some unknown reasons, there is no circle in this graph. The robots can be sent to any point from Earth by rockets. After landing, the robot can visit some points through the roads, and it can choose some points, which are on its roads, to explore. You should notice that the roads of two different robots may contain some same point. 
For financial reason, EUC wants to use minimal number of robots to explore all the points on Mars. 
As an ICPCer, who has excellent programming skill, can your help EUC?

Input

The input will consist of several test cases. For each test case, two integers N (1 <= N <= 500) and M (0 <= M <= 5000) are given in the first line, indicating the number of points and the number of one-way roads in the graph respectively. Each of the following M lines contains two different integers A and B, indicating there is a one-way from A to B (0 < A, B <= N). The input is terminated by a single line with two zeros.

Output

For each test of the input, print a line containing the least robots needed.

Sample Input

1 0
2 1
1 2
2 0
0 0

Sample Output

1
1
2

Source

POJ Monthly--2005.08.28,Li Haoyuan

题目意思:
给一个无环的有向图,求最少多少条路径能把所有点覆盖,其中点是可以重复覆盖的。

思路:

一般的最小路径覆盖要求点不能被重复覆盖,而这道题是可以重复覆盖的。那么怎么转换成最小路径覆盖模型呢?

一个简单的想法就是当要走的点已经被其他路径覆盖过了,那么就跳过这个点直接走到下一个点。floyd处理一下即可。

代码:

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 #include <iostream>
 5 #include <vector>
 6 #include <queue>
 7 #include <cmath>
 8 #include <set>
 9 using namespace std;
10
11 #define N 505
12
13 int max(int x,int y){return x>y?x:y;}
14 int min(int x,int y){return x<y?x:y;}
15 int abs(int x,int y){return x<0?-x:x;}
16
17 int from[N];
18 bool visited[N];
19 int n, m;
20 int map[N][N];
21
22 int march(int u){
23     int i, v;
24     for(v=1;v<=n;v++){
25         if(!visited[v]&&map[u][v]){
26             visited[v]=true;
27             if(from[v]==-1||march(from[v])){
28                 from[v]=u;
29                 return 1;
30             }
31         }
32     }
33     return 0;
34 }
35
36 main()
37 {
38     int i, j, k, u, v;
39     while(scanf("%d %d",&n,&m)==2){
40         if(n==0&&m==0) break;
41         memset(map,0,sizeof(map));
42         for(i=0;i<m;i++){
43             scanf("%d %d",&u,&v);
44             map[u][v]=1;
45         }
46         for(i=1;i<=n;i++){
47             for(j=1;j<=n;j++){
48                 for(k=1;k<=n;k++){
49                     if(map[i][j]&&map[j][k]&&!map[i][k]) map[i][k]=1;
50                 }
51             }
52         }
53         int num=0;
54         memset(from,-1,sizeof(from));
55         for(i=1;i<=n;i++){
56             memset(visited,false,sizeof(visited));
57             if(march(i)) num++;
58         }
59         printf("%d\n",n-num);
60     }
61 }
时间: 2024-08-05 04:39:06

POJ 2594 传递闭包的最小路径覆盖的相关文章

poj 3020 Antenna Placement (最小路径覆盖)

链接:poj 3020 题意:一个矩形中,有n个城市'*','o'表示空地,现在这n个城市都要覆盖无线,若放置一个基站, 那么它至多可以覆盖本身和相邻的一个城市,求至少放置多少个基站才能使得所有的城市都覆盖无线? 思路:求二分图的最小路径覆盖(无向图) 最小路径覆盖=点数-最大匹配数 注:因为为无向图,每个顶点被算了两次,最大匹配为原本的两倍, 因此此时最小路径覆盖=点数-最大匹配数/2 #include<stdio.h> #include<string.h> int edge[4

[POJ] 1422 Air Raid(最小路径覆盖)

题目地址:http://poj.org/problem?id=1422 一个地图上有n个小镇,以及连接着其中两个小镇的有向边,而且这些边无法形成回路.现在选择一些小镇空降士兵(1个小镇最多1个士兵),士兵能沿着边走到尽头,问最少空降几个士兵,能遍历完所有的小镇.最小路径覆盖问题.先拆点,将每个点分为两个点,左边是1到n个点,右边是1到n个点然后每一条有向边对应左边的点指向右边的点 因为最小路径覆盖 = 节点数 - 最大匹配数,所以匈牙利算法求一下二分图最大匹配就能得出结果了. 1 #includ

POJ 1548 Robots(最小路径覆盖)

POJ 1548 Robots 题目链接 题意:乍一看还以为是小白上那题dp,其实不是,就是求一共几个机器人可以覆盖所有路径 思路:最小路径覆盖问题,一个点如果在另一个点右下方,就建边,然后跑最小路径覆盖即可 代码: #include <cstdio> #include <cstring> #include <vector> #include <algorithm> using namespace std; const int N = 25 * 25; in

POJ 1422 二分图(最小路径覆盖)

Air Raid Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 7278   Accepted: 4318 Description Consider a town where all the streets are one-way and each street leads from one intersection to another. It is also known that starting from an i

POJ 1548 (二分图+最小路径覆盖)

题目链接:http://poj.org/problem?id=1548 题目大意:给出一张地图上的垃圾,以及一堆机器人.每个机器人可以从左->右,上->下.走完就废.问最少派出多少个机器人才能捡完所有垃圾. 解题思路: 本题原本是个LIS题.但是有二分图匹配解法. 类似POJ 3020的覆盖题,先不管机器人.把每个点都看作一个中心点.然后从这个点出发,向右.下方向连边,这样这个点就可以看作派出的机器人了. 由于方向固定,怎么连都不会连出反向边,所以是个天然有向图. 跑一遍Hungry,ans=

POJ - 1548 Robots 二分图 最小路径覆盖

题目大意:在一个n * m的地图上面有k个垃圾,问需要派几个机器人才能全部捡完. 机器人的行走路线已经被规划好了,只能从左上向右下走,且只能前进,不能倒退 解题思路:将所有点分成两个点集,点集之间的关系就是能否从该点走到另外一点,如果可以的话,那么关系就存在了 #include<cstdio> #include<cstring> #include<vector> using namespace std; const int N = 1000; struct point

POJ_2594_最小路径覆盖

Treasure Exploration Time Limit: 6000MS   Memory Limit: 65536K Total Submissions: 8085   Accepted: 3303 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传递闭包】

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【传递闭包+最小路径覆盖】

大意: 有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+