hdu1845-二分图

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1845

Description
Jimmy is studying Advanced Graph Algorithms at his university. His most recent assignment is to find a maximum matching in a special kind of graph. This graph is undirected, has N vertices and each vertex has degree 3. Furthermore, the graph is 2-edge-connected (that is, at least 2 edges need to be removed in order to make the graph disconnected). A matching is a subset of the graph’s edges, such that no two edges in the subset have a common vertex. A maximum matching is a matching having the maximum cardinality.
Given a series of instances of the special graph mentioned above, find the cardinality of a maximum matching for each instance.

Input

The first line of input contains an integer number T, representing the number of graph descriptions to follow. Each description contains on the first line an even integer number N (4<=N<=5000), representing the number of vertices. Each of the next 3*N/2 lines contains two integers A and B, separated by one blank, denoting that there is an edge between vertex A and vertex B. The vertices are numbered from 1 to N. No edge may appear twice in the input.

Output
For each of the T graphs, in the order given in the input, print one line containing the cardinality of a maximum matching.

Sample Input
2
4
1 2
1 3
1 4
2 3
2 4
3 4
4
1 2
1 3
1 4
2 3
2 4
3 4

Sample Output
2
2

题意
给出t组数据
每组数据给出偶数个点,保证每个点有3个度
之后的3*n/2行每行表示两个点之间有一条无向边。
问最大匹配为多少。

思路
比较裸的二分图,匈牙利写的不好会T,写好了900ms+,sqrt优化后稳过。

吐槽
一开始憨憨的二分图,结果做完去搜发现可以推出n/2就是最后答案…

匈牙利900ms

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define lson l,mid,i<<1
#define rson mid+1,r,i<<1|1
using namespace std;
typedef long long ll;
const int maxn = 5010;
int link[maxn];
int vis[maxn];
vector<int>mp[maxn];
int un, vn;
bool dfs(int u) {
for (int i = 0; i < mp[u].size(); i++) {
int v = mp[u][i];
if (!vis[v]) {
vis[v] = 1;
if (link[v] == -1 || dfs(link[v])) {
link[v] = u;
return 1;
}
}
}
return 0;
}
int xyl() {
int ans = 0;
memset(link, -1, sizeof(link));
for (int i = 1; i <=un; i++) {
memset(vis, 0, sizeof(vis));
if (dfs(i))
ans++;
}
return ans;
}
int main() {
int t;
cin >> t;
while (t--) {
int n;
scanf("%d", &n);
for (int i = 0; i <= n; i++) {
mp[i].clear();
}
int x, y;
for (int i = 0; i < 3 * n / 2; i++) {
scanf("%d%d", &x, &y);
mp[x].push_back(y);
mp[y].push_back(x);
}
un = vn = n;
printf("%d\n", xyl() / 2);
}
}

优化后300ms

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define lson l,mid,i<<1
#define rson mid+1,r,i<<1|1
using namespace std;
typedef long long ll;
const int maxn = 5010;
const int INF = 2e9;
vector<int>mp[maxn];
int Mx[maxn], My[maxn];//Mx表示左集合点i增广路连着那个右节点,My表示右集合点i增广路连着那个左节点
int dx[maxn], dy[maxn];
int dis;
int Nx, Ny;
bool vis[maxn];
bool SearchP() {
queue<int>Q;
dis = INF;
memset(dx, -1, sizeof(dx));
memset(dy, -1, sizeof(dy));
for (int i = 1; i <= Nx; i++)
if (Mx[i] == -1) {
Q.push(i);
dx[i] = 0;
}
while (!Q.empty()) {
int u = Q.front();
Q.pop();
if (dx[u] > dis)
break;
for (int i = 0; i < mp[u].size(); i++) {
int v = mp[u][i];
if (dy[v] == -1) {
dy[v] = dx[u] + 1;
if (My[v] == -1)
dis = dy[v];
else {
dx[My[v]] = dy[v] + 1;
Q.push(My[v]);
}
}
}
}
return dis != INF;
}
bool DFS(int u) {
for (int i = 0; i < mp[u].size(); i++) {
int v = mp[u][i];
if (!vis[v] && dy[v] == dx[u] + 1) {
vis[v] = true;
if (My[v] != -1 && dy[v] == dis)continue;
if (My[v] == -1 || DFS(My[v])) {
My[v] = u;
Mx[u] = v;
return true;
}
}
}
return false;
}
int MaxMatch() {
int res = 0;
memset(Mx, -1, sizeof(Mx));
memset(My, -1, sizeof(My));
while (SearchP()) {
memset(vis, false, sizeof(vis));
for (int i = 1; i <= Nx; i++)
if (Mx[i] == -1 && DFS(i))
res++;
}
return res;
}
int main() {
int t;
cin >> t;
while (t--) {
int n;
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
mp[i].clear();
}
int x, y;
for (int i = 0; i < 3 * n / 2; i++) {
scanf("%d%d", &x, &y);
mp[x].push_back(y);
mp[y].push_back(x);
}
Nx = Ny = n;
printf("%d\n", MaxMatch() / 2);
}
}

谢谢你请我吃糖果

你可能感兴趣的:(hdu1845-二分图)