Note:
There are n vertices, which tell you how many vertices can cover all vertices. [Note that vertices can overlap for example, 4-> 1-> 2 5-> 3]
Analysis:
Knowledge reserve:
Transfer closure: the so-called transfer, it can be understood that for node J, if I can reach K and K can reach J, then I can reach J. In this way, like floyed, it can process whether the specified two points can arrive
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]); } } }}
Because the points can be reused, the passing closure is used to process the arrival relationship between any two points.
You can find the minimum path overwrite.
Code:
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 }
View code
Poj 2594 treasure transition ation [transfer closure + minimum path overwrite]