Adam just moved into his new apartment and simply placed everything into it at random. This means in particular that he did not put any effort into placing his electronics in a way that each one can have its own electric socket.
Since the cables of his devices have limited reach, not every device can be plugged into every socket without moving it first. As he wants to use as many electronic devices as possible right away without moving stuff around, he now tries to figure out which device to plug into which socket. Luckily the previous owner left behind a plugbar which turns one electric socket into 3.
Can you help Adam figure out how many devices he can power in total?
Input
The input consists of:
• one line containing three integers m, n and k, where
– m (1 ≤ m ≤ 1 500) is the number of sockets;
– n (1 ≤ n ≤ 1 500) is the number of electronic devices;
– k (0 ≤ k ≤ 75 000) is the number of possible connections from devices to sockets.
• k lines each containing two integers xi and yi indicating that socket xi can be used to power device yi .
Sockets as well as electronic devices are numbered starting from 1.
The plugbar has no cable, i.e. if it is plugged into a socket it simply triples it.
Output
Output one line containing the total number of electrical devices Adam can power.
Sample Input 1
3 6 8
1 1
1 2
1 3
2 3
2 4
3 4
3 5
3 6
Sample Output 1
5
Sample Input 2
4 5 11
1 1
1 2
1 3
2 1
2 2
2 3
3 1
3 2
3 3
4 4
4 5
Sample Output 2
5
Sample Input 3
3 5 7
1 1
1 2
2 2
2 3
2 4
3 4
3 5
Sample Output 3
5
#include <bits/stdc++.h>
using namespace std;
const int mm = 1510, mn = 1510, mk = 75010;
int m, n, k;
bool vis[mn];
int con[mn], tcon[mn];
int num;
int from[mk + 2 * mn], to[mk + 2 * mn], nx[mk + 2 * mn], fr[mm];
void addedge(int a, int b)
{
num++;
from[num] = a;
to[num] = b;
nx[num] = fr[a];
fr[a] = num;
}
bool pipei(int s)
{
for (int i = fr[s]; i != -1; i = nx[i])
{
int t = to[i];
if (!vis[t])
{
vis[t] = 1;
if (!con[t] || pipei(con[t]))
{
con[t] = s;
return 1;
}
}
}
return 0;
}
int xyl()
{
int ans = 0;
for (int i = 1; i <= m; i++)
{
memset(vis, 0, sizeof vis);
if (pipei(i))
ans ++;
}
return ans;
}
int main()
{
memset(fr, -1, sizeof fr);
scanf("%d %d %d", &m, &n, &k);
while (k--)
{
int a, b;
scanf("%d %d", &a, &b);
addedge(a, b);
}
int ansnum = num;
int ans = xyl();
/// 匈牙利算法得出初始可匹配数量
int tans = 0;
for (int i = 1; i <= n; i++)
tcon[i] = con[i];
for (int i = 1; i <= m; i++) /// 枚举加接线板的插头
{
int temp = 0;
for (int j = 1; j <= n; j++)
con[j] = tcon[j]; // 还原为不增加插头时的匹配
for (int k = 1; k <= 2; k++) // 复制边
{
for (int j = fr[i]; j != -1; j = nx[j])
addedge(m + k, to[j]);
}
memset(vis, 0, sizeof vis);
if (pipei(m + 1)) // 如果新增的插头能匹配上
temp++;
memset(vis, 0, sizeof vis);
if (pipei(m + 2))
temp++;
tans = max(tans, temp);
for (int k = 1; k <= 2; k++) // 删去新增的两个插头
fr[m + k] = -1;
num = ansnum;
}
printf("%d\n", tans + ans);
return 0;
}