题目描述
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?
输入
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 one line containing the total number of electrical devices Adam can power.
样例输入
3 6 8
1 1
1 2
1 3
2 3
2 4
3 4
3 5
3 6
样例输出
5
思路
先跑一遍匈牙利算法,记录原始状态下的最佳匹配,然后枚举每一个插座,对于每一次枚举,复制两个与该插座有相同电器关系的插座,以实现题目条件,对复制出的插座再进行两次匈牙利算法,最后求出的最佳结果即为答案,注意每次的初始化
代码实现
#pragma GCC optimize(3,"Ofast","inline")
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1510;
const int maxm=1510;
typedef pair<string,string> P;
const double eps=1e-8;
const double PI=acos(-1.0);
int g[maxn][maxn];
int linker[maxn];
int tlinker[maxn];
bool used[maxn];
int m,n,k,len;
inline bool dfs(int u)
{
for(register int v=1;v<=n;++v)
{
if(g[u][v] && !used[v])
{
used[v]=true;
if(linker[v]==-1 || dfs(linker[v]))
{
linker[v]=u;
return true;
}
}
}
return false;
}
inline int hungry()
{
int res=0,ans=0;;
memset(linker,-1,sizeof(linker));
for(int u=1;u<=m;++u)
{
memset(used,false,sizeof(used));
if(dfs(u)) res++;
}
for(int i=1;i<=n;++i)
{
tlinker[i]=linker[i];
}
for(int u=1;u<=m;u++)
{
int temp=0;
for(int i=1;i<=n;++i)
{
linker[i]=tlinker[i];
}
for(int i=1;i<=n;i++)
{
g[m+1][i]=g[u][i];
g[m+2][i]=g[u][i];
}
memset(used,false,sizeof(used));
if(dfs(m+1)) temp++;
memset(used,false,sizeof(used));
if(dfs(m+2)) temp++;
ans=max(ans,temp+res);
}
return ans;
}
int main()
{
ios::sync_with_stdio(false);
cin>>m>>n>>k;
for(register int i=0;i<k;++i)
{
int u,v;
cin>>u>>v;
g[u][v]=1;
}
cout<<hungry()<<endl;
return 0;
}