#include <bits/stdc++.h>
using namespace std;
const int N=100050;
const int M=100050;
int n,m;
struct Edge{int v,next;}edge[M];
int cnt,head[N];
void init() {cnt=0; memset(head,-1,sizeof(head));}
void addEdge(int u,int v)
{
edge[cnt]=Edge{v,head[u]};
head[u]=cnt++;
}
//Left表示右边点集的左边匹配点
int Left[N],Right[N];
//S T分别表示左右点集是否已匹配
bool S[N],T[N];
//X Y表示左右两边的最小覆盖点集
vector<int> X,Y;
bool dfs(int u)
{
S[u]=true;
for(int i=head[u];i!=-1;i=edge[i].next)
{
int v=edge[i].v;
if(!T[v])
{
T[v]=true;
if(Left[v]==-1 || dfs(Left[v]))
{
Left[v]=u;
Right[u]=v;
return true;
}
}
}
return false;
}
void solve()
{
int ans;
memset(S,0,sizeof(S));
memset(T,0,sizeof(T));
memset(Left,-1,sizeof(Left));
memset(Right,-1,sizeof(Right));
for (int i = 1;i <= n;i++)
{
memset(T,0,sizeof(T));
ans += dfs(i);
}
//ans表示最小点覆盖数(最大匹配)
cout<<ans<<endl;
memset(S,0,sizeof(S));
memset(T,0,sizeof(T));
//左边没有匹配的点再增广下去
for(int i=1;i<=n;i++)
{
if(Right[i]==-1) dfs(i);
}
//此时最小点覆盖集即是左边没标记的点
for(int u=1;u<=n;u++)
if(!S[u]) X.push_back(u);
//和右边已标记的点
for(int v=1;v<=m;v++)
if(T[v]) Y.push_back(v);
}
int main()
{
//n、m:左右点数
//addEdge(i,j) 左边的i往右边的j连边
//调用solve()
//X、Y:最小点覆盖
//补集:最大独立集合
}
【模板】最小点覆盖、最大独立集
最新推荐文章于 2020-03-02 20:28:20 发布