题目地址:HDU 3861
这题虽然是两个算法结合起来的。但是感觉挺没意思的。。结合的一点也不自然,,硬生生的揉在了一块。。。(出题者不要喷我QAQ。)
不过这题让我发现了我的二分匹配已经好长时间没用过了。。都快忘了。。正好在省赛之前又复习了一下。
代码如下:
#include <iostream>
#include <string.h>
#include <math.h>
#include <queue>
#include <algorithm>
#include <stdlib.h>
#include <map>
#include <set>
#include <stdio.h>
using namespace std;
#define LL __int64
#define pi acos(-1.0)
const int mod=1e9+7;
const int INF=0x3f3f3f3f;
const double eqs=1e-9;
const int MAXN=5000+50;
const int MAXM=100000+50;
int head[MAXN], cnt, indx, top, ans;
int low[MAXN], dfn[MAXN], belong[MAXN], instack[MAXN], stk[MAXN];
struct node
{
int u, v, next;
}edge[MAXM];
void add(int u, int v)
{
edge[cnt].v=v;
edge[cnt].u=u;
edge[cnt].next=head[u];
head[u]=cnt++;
}
void tarjan(int u)
{
low[u]=dfn[u]=++indx;
instack[u]=1;
stk[++top]=u;
for(int i=head[u];i!=-1;i=edge[i].next){
int v=edge[i].v;
if(!dfn[v]){
tarjan(v);
low[u]=min(low[u],low[v]);
}
else if(instack[v]){
low[u]=min(low[u],dfn[v]);
}
}
if(low[u]==dfn[u]){
ans++;
while(1){
int v=stk[top--];
instack[v]=0;
belong[v]=ans;
if(u==v) break;
}
}
}
void init()
{
memset(head,-1,sizeof(head));
memset(dfn,0,sizeof(dfn));
memset(instack,0,sizeof(instack));
cnt=indx=top=ans=0;
}
int head1[MAXN], cnt1, vis[MAXN], link[MAXN];
struct N
{
int u, v, next;
}edge1[MAXM*2];
void add1(int u, int v)
{
edge1[cnt1].v=v;
edge1[cnt1].next=head1[u];
head1[u]=cnt1++;
}
int dfs(int u)
{
for(int i=head1[u];i!=-1;i=edge1[i].next){
int v=edge1[i].v;
if(!vis[v]){
vis[v]=1;
if(link[v]==-1||dfs(link[v])){
link[v]=u;
return 1;
}
}
}
return 0;
}
void hungary()
{
memset(link,-1,sizeof(link));
int i, sum=0;
for(i=1;i<=ans;i++){
memset(vis,0,sizeof(vis));
sum+=dfs(i);
}
printf("%d\n",ans-sum);
}
int main()
{
int t, n, m, u, v, i;
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&m);
init();
while(m--){
scanf("%d%d",&u,&v);
add(u,v);
}
for(i=1;i<=n;i++){
if(!dfn[i]) tarjan(i);
}
memset(head1,-1,sizeof(head1));
cnt1=0;
for(i=0;i<cnt;i++){
u=belong[edge[i].u];
v=belong[edge[i].v];
if(u!=v){
add1(u,v);
}
}
hungary();
}
return 0;
}