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 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 题意: 一个星球上有n个点,给出几条路,机器人可以沿着路遍历,问要遍历完整个星球最少需要几个机器人 注意每个点可以重复遍历 思路:最小路径覆盖,二分图最大匹配,和floyd缩点: 什么叫最小路径覆盖? 就是说,在当前的图上,找N条路径,让这N条路径覆盖图上所有的点, N的最小值就是我们要求的值。根据具体问题的不同,可分为一个顶点只能经过一次, 和可以经过多次两类。 最小路径覆盖的算法原理叙述如下:由于每条路径是一串点的序列, 所以除了终点之外,每个点都有(不一定只有,这是我们等会要讨论的第二类问题。)一个后继,所以我们就用后继为关系建图,把每个点拆为起点和终点。终点放在二分图左侧,起点放在右侧,如果x-y有边,那么就在x的终点和y的起点间连边,求一遍匹配,没有被匹配到的点是干什么的?对,是路径的终点,因为只有路径的终点没有后继, 所以没有被匹配的点,就是路径的条数。(左为原图,右为建好的二分图) 那一个点可以经过多次怎么办?如果一个点可以经过多次,Cjf神牛说了:“缩点!” 缩点完了和上面的做法一样,至于缩点用Floyed。 二分图最大匹配用匈牙利算法, 2015,7,24#include<stdio.h> #include<string.h> int path[510][510],vis[510]; int mac[510]; int n,m; void floyd() { for(int k=1;k<=n;k++) for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) { if(path[i][k]&&path[k][j]) path[i][j]=1; } } int Find(int k) { for(int i=1;i<=n;i++)//遍历每个点 { if(!vis[i]&&path[k][i]==1)//如果这个点没有被访问过,而且有路存在 { vis[i]=1; if(!mac[i]||Find(mac[i]))//并且这条路没有前驱节点,可以腾出来一个(递归)这可以理解为hdu 2063的对象详见博客 { mac[i]=k; return 1; } } } return 0; } int main() { int i,j,a,b,num; while(scanf("%d%d",&n,&m),n+m) { memset(path,0,sizeof(path)); for(i=0;i<m;i++) { scanf("%d%d",&a,&b); path[a][b]=1;//注意这是有向图,找了半天错 } floyd(); num=0; memset(mac,0,sizeof(mac)); for(i=1;i<=n;i++) { memset(vis,0,sizeof(vis)); if(Find(i)) num++; } printf("%d\n",n-num); } return 0; }