您的位置:首页 > 其它

loj 1429(可相交的最小路径覆盖)

2014-05-26 18:09 369 查看
题目链接:http://lightoj.com/volume_showproblem.php?problem=1429

思路:这道题还是比较麻烦的,对于求有向图的可相交的最小路径覆盖,首先要解决成环问题,可以先染色缩点重建图,然后就是如何来处理这个路径可以相交这个问题,这里可以用bfs求出任意两点之间是否可达,如果可达,就连边,然后就是HK算法求最大匹配了,最小路径覆盖 = 顶点数 - 最大匹配。





1 #include <iostream>
2 #include <cstdio>
3 #include <cstring>
4 #include <algorithm>
5 #include <vector>
6 #include <queue>
7 #include <stack>
8 using namespace std;
9
10 const int MAXN = (1000 + 10);
11 const int MAXM = (10000 + 10);
12 int n, m;
13 int cnt, scc_count;
14 bool Instack[MAXN];
15 int low[MAXN], dfn[MAXN], color[MAXN];
16 vector<int > g[MAXN];
17 stack<int > S;
18
19 void Tarjan(int u)
20 {
21     low[u] = dfn[u] = ++cnt;
22     Instack[u] = true;
23     S.push(u);
24     for (int i = 0; i < (int)g[u].size(); i++) {
25         int v = g[u][i];
26         if (dfn[v] == 0) {
27             Tarjan(v);
28             low[u] = min(low[u], low[v]);
29         } else if (Instack[v]) {
30             low[u] = min(low[u], dfn[v]);
31         }
32     }
33     if (low[u] == dfn[u]) {
34         scc_count++;
35         int v;
36         do {
37             v = S.top();
38             S.pop();
39             Instack[v] = false;
40             color[v] = scc_count;
41         } while (u != v);
42     }
43 }
44
45 bool Isok[MAXN][MAXN];
46 bool mark[MAXN];
47 vector<int > reg[MAXN];
48
49 void bfs(int st)
50 {
51     memset(mark, false, sizeof(mark));
52     queue<int >que;
53     que.push(st);
54     mark[st] = true;
55     while (!que.empty()) {
56         int u = que.front();
57         que.pop();
58         for (int i = 0; i < (int)reg[u].size(); i++) {
59             int v = reg[u][i];
60             if (!mark[v]) {
61                 mark[v] = true;
62                 que.push(v);
63             }
64         }
65     }
66 }
67
68 void Build()
69 {
70     for (int i = 1; i <= scc_count; i++) {
71         reg[i].clear();
72     }
73     for (int i = 1; i <= scc_count; i++) {
74         for (int j = 1; j <= scc_count; j++) {
75             if (i != j && Isok[i][j]) {
76                 reg[i].push_back(j);
77             }
78         }
79     }
80 }
81
82 int lx[MAXN], ly[MAXN];
83 int distx[MAXN], disty[MAXN];
84
85 bool MaxMatch_bfs()
86 {
87     bool flag = false;
88     memset(distx, 0, sizeof(distx));
89     memset(disty, 0, sizeof(disty));
90     queue<int > que;
91     for (int i = 1; i <= scc_count; i++) {
92         if (lx[i] == -1) que.push(i);
93     }
94     while (!que.empty()) {
95         int u = que.front();
96         que.pop();
97         for (int i = 0; i < (int)reg[u].size(); i++) {
98             int v = reg[u][i];
99             if (disty[v] == 0) {
100                 disty[v] = distx[u] + 1;
101                 if (ly[v] == -1) flag = true;
102                 else {
103                     distx[ly[v]] = disty[v] + 1;
104                     que.push(ly[v]);
105                 }
106             }
107         }
108     }
109     return flag;
110 }
111
112 int dfs(int u)
113 {
114     for (int i = 0; i < (int)reg[u].size(); i++) {
115         int v = reg[u][i];
116         if (disty[v] == distx[u] + 1) {
117             disty[v] = 0;
118             if (ly[v] == -1 || dfs(ly[v])) {
119                 ly[v] = u;
120                 lx[u] = v;
121                 return 1;
122             }
123         }
124     }
125     return 0;
126 }
127
128 int MaxMatch()
129 {
130     memset(lx, -1, sizeof(lx));
131     memset(ly, -1, sizeof(ly));
132     int res = 0;
133     while (MaxMatch_bfs()) {
134         for (int i = 1; i <= scc_count; i++) {
135             if (lx[i] == -1) res += dfs(i);
136         }
137     }
138     return res;
139 }
140
141
142 int main()
143 {
144     int _case, t = 1;
145     scanf("%d", &_case);
146     while (_case--) {
147         scanf("%d %d", &n, &m);
148         for (int i = 1; i <= n; i++) {
149             g[i].clear();
150             reg[i].clear();
151         }
152         while (m--) {
153             int u, v;
154             scanf("%d %d", &u, &v);
155             g[u].push_back(v);
156         }
157         //强联通缩点重建图
158         cnt = scc_count = 0;
159         memset(dfn, 0, sizeof(dfn));
160         for (int i = 1; i <= n; i++) {
161             if (dfn[i] == 0) Tarjan(i);
162         }
163         for (int u = 1; u <= n; u++) {
164             for (int i = 0; i < (int)g[u].size(); i++) {
165                 int v = g[u][i];
166                 if (color[u] != color[v]) {
167                     reg[color[u]].push_back(color[v]);
168                 }
169             }
170         }
171         //bfs求出新图中的任意两点之间是否可达
172         memset(Isok, false, sizeof(Isok));
173         for (int i = 1; i <= scc_count; i++) {
174             bfs(i);
175             for (int j = 1; j <= scc_count; j++) {
176                 if (mark[j]) {
177                     Isok[i][j] = true;
178                 }
179             }
180         }
181         //对于那些可达的点重新连边
182         Build();
183         //bfs求解最大匹配;
184         //最小路径覆盖 = 顶点数 - 最大匹配数
185         int ans = MaxMatch();
186         printf("Case %d: %d\n", t++, scc_count- ans);
187     }
188     return 0;
189 }


View Code
 

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: