这题跟传统的路径覆盖不同的是任意两条路径间可以相交点
这就需要进行一些改变
有一个大牛解释的非常好,如果一个机器人在路上走着,碰到了别的路径的点,那就直接飞过去好了。也就是直接到了之前间接能到的点。
那么我们事先用floyd把每个点能到达的点,不管是直接或者间接能达到的,处理一下
然后建图就好了
#include <iostream> #include <algorithm> #include <cstring> #include <string> #include <cstdio> #include <cmath> #include <queue> #include <map> #include <set> #define eps 1e-5 #define MAXN 555 #define MAXM 320005 #define INF 100000007 using namespace std; int d[MAXN][MAXN], n; struct EDGE { int v, next; }edge[MAXM]; int head[MAXN], e, link[MAXN], vis[MAXN]; void init() { memset(head, -1, sizeof(head)); e = 0; } void add(int x, int y) { edge[e].v = y; edge[e].next = head[x]; head[x] = e++; } int dfs(int u) { for(int i = head[u]; i != -1; i = edge[i].next) { int v = edge[i].v; if(!vis[v]) { vis[v] = 1; if(link[v] == -1 || dfs(link[v])) { link[v] = u; return 1; } } } return 0; } int solve() { int ans = 0; memset(link, -1, sizeof(link)); for(int i = 1; i <= n; i++) { memset(vis, 0, sizeof(vis)); ans += dfs(i); } return ans; } void floyd() { for(int k = 1; k <= n; k++) for(int i = 1; i <= n; i++) if(d[i][k]) for(int j = 1; j <= n; j++) if(d[k][j]) d[i][j] = 1; } int main() { int m; while(scanf("%d%d", &n, &m) != EOF) { if(!n && !m) break; int u, v; memset(d, 0, sizeof(d)); init(); for(int i = 0; i < m; i++) { scanf("%d%d", &u, &v); d[u][v] = 1; } floyd(); for(int i = 1; i <= n; i++) for(int j = 1; j <= n; j++) { if(i == j) continue; if(d[i][j]) add(i, j); } printf("%d\n", n - solve()); } return 0; }