poj2594

特殊的最小路径覆盖
回顾一下经典的最小路径覆盖问题是每个点都恰好被一条路径覆盖
我们把有向无环图的点拆成i,i',对于原图中边i--->j,连边i-->j'
做最大匹配,答案是原图点数-最大匹配
但这道题每个点可以被覆盖多次,所以我们考虑先dfs出每个点可以访问的点
然后拆点,如果i可以到达j,那么连边i-->j',答案是原图点数-最大匹配
为什么呢,感性的想一下,在最小路径覆盖的基础上既然每个点可以被多次经过
那么干脆我们把两个可达的点认为是直接飞过去就好了~ ~

 1 type node=record
 2        point,next:longint;
 3      end;
 4 
 5 var edge:array[0..200010] of node;
 6     a:array[0..510,0..510] of boolean;
 7     p,cx,cy:array[0..510] of longint;
 8     v:array[0..510] of boolean;
 9     x,y,n,m,i,j,ans,len:longint;
10 
11 procedure add(x,y:longint);
12   begin
13     inc(len);
14     edge[len].point:=y;
15     edge[len].next:=p[x];
16     p[x]:=len;
17   end;
18 
19 function find(x:longint):longint;
20   var i,y:longint;
21   begin
22     i:=p[x];
23     while i<>-1 do
24     begin
25       y:=edge[i].point;
26       if not v[y] then
27       begin
28         v[y]:=true;
29         if (cy[y]=-1) or (find(cy[y])=1) then
30         begin
31           cx[x]:=y;
32           cy[y]:=x;
33           exit(1);
34         end;
35       end;
36       i:=edge[i].next;
37     end;
38     exit(0);
39   end;
40 
41 procedure dfs(x:longint);
42   var i,y:longint;
43   begin
44     i:=p[x];
45     v[x]:=true;
46     while i<>-1 do
47     begin
48       y:=edge[i].point;
49       if not v[y] then dfs(y);
50       i:=edge[i].next;
51     end;
52   end;
53 
54 begin
55   readln(n,m);
56   while (n<>0) do
57   begin
58     ans:=0;
59     len:=0;
60     fillchar(p,sizeof(p),255);
61     fillchar(a,sizeof(a),false);
62     for i:=1 to m do
63     begin
64       readln(x,y);
65       add(x,y);
66       a[x,y]:=true;
67     end;
68     for i:=1 to n do
69     begin
70       fillchar(v,sizeof(v),false);
71       dfs(i);
72       for j:=1 to n do
73         if v[j] and (i<>j) and not a[i,j] then
74           add(i,j);
75     end;
76     fillchar(cx,sizeof(cx),255);
77     fillchar(cy,sizeof(cy),255);
78     for i:=1 to n do
79       if cx[i]=-1 then
80       begin
81         fillchar(v,sizeof(v),false);
82         ans:=ans+find(i);
83       end;
84     writeln(n-ans);
85     readln(n,m);
86   end;
87 end.
View Code
原文地址:https://www.cnblogs.com/phile/p/4473080.html