1,ICPC Pacific Northwest Regional Contest 2019 -I
求给定的无向图,互不到达的点集的大小。(nle500) 。
(ans=n-) 最大二分图匹配数目
(code:)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e3+5;
const int inf=0x3f3f3f3f;
void read(int&x)
{
char c;
while(!isdigit(c=getchar()));x=c-'0';
while(isdigit(c=getchar()))x=(x<<3)+(x<<1)+c-'0';
}
char s[505][30];
vector<int>p[505];
int match[505];
bool vis[505];
int dfs(int u)
{
for(int v:p[u])
{
if(vis[v])continue;
vis[v]=1;
if(!match[v]||dfs(match[v]))
{
match[v]=u;
match[u]=v;
return 1;
}
}
return 0;
}
int main()
{
int n;
read(n);
for(int i=1;i<=n;i++)
scanf("%s",s[i]);
int len=strlen(s[1]),t;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
t=0;
for(int k=0;k<len;k++)
if(s[i][k]!=s[j][k])t++;
if(t==2)
{
p[i].push_back(j);
p[j].push_back(i);
}
}
}
int ans=0;
for(int i=1;i<=n;i++)
{
memset(vis,0,sizeof vis);
vis[i]=1;
if(!match[i]&&dfs(i))ans++;
}
printf("%d
",n-ans);
}
2,ACM_ICPC 2017 Asia Nanning -M
求给定的有向无环图,互不到达的最大点集的大小。
(Tle500,\,nle100,\,mle n*(n-1)/2,;sum mle500000) 。
做法:对每个点与其能到达的点连边,得到一个新的有向图,对这个有向图求最大二分图匹配,答案则为 (n)-最大二分图匹配数。
注意有向图和无向图二分匹配的区别:无向图二分匹配后结果 每个点最多只能有一个匹配边,有向图二分匹配结果,每个点最多能有一条指向外的匹配边和指向自己的匹配边(即出度入度各位1).
(code:)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e3+5;
const int inf=0x3f3f3f3f;
void read(int&x)
{
char c;
while(!isdigit(c=getchar()));x=c-'0';
while(isdigit(c=getchar()))x=(x<<3)+(x<<1)+c-'0';
}
vector<int>p[105];
int out[105],in[105];
bool vis[105];
bool dfs(int u)
{
for(int v:p[u])
{
if(vis[v])continue;
vis[v]=1;
if(!in[v]||dfs(in[v]))
{
in[v]=u;
out[u]=v;
return 1;
}
}
return 0;
}
bool eg[105][105];
int main()
{
int T;
read(T);
while(T--)
{
int n,m,u,v;
read(n);read(m);
memset(eg,0,sizeof(eg));
memset(in,0,sizeof(in));
memset(out,0,sizeof(out));
for(int i=1;i<=n;i++)p[i].clear();
for(int i=1;i<=m;i++)
{
read(u);read(v);
eg[u][v]=1;
}
for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(eg[i][k]&&eg[k][j])eg[i][j]=1;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(i!=j&&eg[i][j])p[i].push_back(j);
int tn=0;
for(int i=1;i<=n;i++)
{
memset(vis,0,sizeof vis);
if(!out[i]&&dfs(i))tn++;
}
printf("%d
",n-tn);
}
}