HDU 3861
最小不相交路径覆盖,利用匈牙利算法实现
模板
bool dfs_cp(int x){
int i;
for(i=0;i<sv[x].size();i++){
int y=sv[x][i];
if(have[y])
continue;
have[y]=true;
if(!match[y]||dfs_cp(match[y])){
match[y]=x;
return true;
}
}
return false;
}
int solve(int n){
int res=0,i;
memset(match,0,sizeof(match));
for(i=1;i<=n;i++){
memset(have,0,sizeof(have));
res+=dfs_cp(i);
}
return n-res;
}
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;
const int MAX_N=5010;
int match[MAX_N];
bool have[MAX_N];
int ans;//强连通分量的个数
int low[MAX_N],num[MAX_N],cnt;
int stack[MAX_N],top;
int vis[MAX_N];
vector<int>v[MAX_N],sv[MAX_N];
void dfs(int now){
int i;
stack[top++]=now;
low[now]=num[now]=++cnt;
for(i=0;i<v[now].size();i++){
int to=v[now][i];
if(!num[to]){
dfs(to);
low[now]=min(low[now],low[to]);
}
else if(!vis[to])
low[now]=min(low[now],num[to]);
}
if(low[now]==num[now]){
ans++;
while(1){
int to=stack[--top];
vis[to]=ans;
if(now==to)
break;
}
}
}
void tarjan(int n){
int i,j;
ans=cnt=top=0;
memset(vis,0,sizeof(vis));
memset(num,0,sizeof(num));
memset(low,0,sizeof(low));
for(i=1;i<=n;i++){
if(!num[i])
dfs(i);
}
for(i=1;i<=n;i++){
for(j=0;j<v[i].size();j++){
int to=v[i][j];
if(vis[i]!=vis[to])
sv[vis[i]].push_back(vis[to]);
}
}
}
bool dfs_cp(int x){
int i;
for(i=0;i<sv[x].size();i++){
int y=sv[x][i];
if(have[y])
continue;
have[y]=true;
if(!match[y]||dfs_cp(match[y])){
match[y]=x;
return true;
}
}
return false;
}
int solve(int n){
int res=0,i;
memset(match,0,sizeof(match));
for(i=1;i<=n;i++){
memset(have,0,sizeof(have));
res+=dfs_cp(i);
}
return n-res;
}
int main(void){
int T,n,m,i,a,b;
cin>>T;
while(T--){
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++){
v[i].clear();
sv[i].clear();
low[i]=0;
num[i]=0;
vis[i]=0;
}
for(i=0;i<m;i++){
scanf("%d%d",&a,&b);
v[a].push_back(b);
}
tarjan(n);
printf("%d\n",solve(ans));
}
return 0;
}