UVA1184 Air Raid / YbtOJ「图论」第1章 二分图匹配 G. 伞兵空降 题解--zhengjun

思路

问题转化为了在一张 dag 图上求出最小路径覆盖,见洛谷P2764题解

只需要用二分图匹配,每一次连接了一对匹配,相当于合并了两条路径(单个点也认为是路径),所以要让路径总数最小,就要让匹配的数量最大,由于是路径,所以每个点的入点和出点都最多只能连两条边。

代码

#include<bits/stdc++.h>
using namespace std;typedef long long ll;const int N=3e2+10,M=N*N;
int T,n,m,s,t,head[N],kk,d[N],cur[N];struct edges{int to,c,nex;}edge[M];
void add(int u,int v,int c){edge[++kk]={v,c,head[u]};head[u]=kk;edge[++kk]={u,0,head[v]};head[v]=kk;}
bool bfs(){
	memset(d,-1,sizeof d);d[s]=0;cur[s]=head[s];queue<int>q;for(q.push(s);!q.empty();q.pop()){
		int u=q.front();for(int i=head[u],v;v=edge[i].to,i;i=edge[i].nex)
			if(d[v]==-1&&edge[i].c)d[v]=d[u]+1,cur[v]=head[v],q.push(v);
	}return d[t]!=-1;
}
int dfs(int u,int lim=1e9){
	if(u==t)return lim;int flow=0;for(int i=head[u],v;v=edge[i].to,i&&flow<lim;i=edge[i].nex){
		cur[u]=i;if(d[v]!=d[u]+1||!edge[i].c)continue;int f=dfs(v,min(lim-flow,edge[i].c));
		if(!f)d[v]=-1;edge[i].c-=f;edge[i^1].c+=f;flow+=f;
	}return flow;
}
int dinic(){int maxflow=0;while(bfs())maxflow+=dfs(s);return maxflow;}
void clear(){memset(head,0,sizeof head);kk=1;}
void get(){
	clear();scanf("%d%d",&n,&m);for(int i=1,u,v;i<=m;i++)scanf("%d%d",&u,&v),add(u,v+n,1);
	s=0;t=n+n+1;for(int i=1;i<=n;i++)add(s,i,1),add(i+n,t,1);printf("%d\n",n-dinic());
}
int main(){
	for(cin>>T;T--;)get();return 0;
}
posted @ 2022-06-27 21:23  A_zjzj  阅读(19)  评论(0编辑  收藏  举报