Topic links:
https://www.luogu.com.cn/problem/P1640
Reference blog:
https://www.luogu.com.cn/blog/xuanxue/solution-p1640
Blog is great, it is recommended to look at review
Algorithm: 1: Hungary Algorithm 2: Before the chain to star
Ideas:
1: man sister model, man is the attribute number 1-10000, the sister is the number of weapons 1-1000000
2: Let each and every property and equipment to even numbered side
3: attribute points from small to large order match, so we do not consider there will be no legal case, a time when we can not match attribute points i, we get the answer i-1
4: Hungarian algorithm is only used to build a one-way side, because every time we update when they are only use one side of the updated point, less than the other side of the point.
5: Another n = 106n = 10 ^ 6n = 106 when we can not always memset, or else it will time out, we record what point in time, when traversing look at the point in time is not a conflict can be. About this time stamp usage now, you can give a simple example of an analog look, very clever
#include <bits/stdc++.h>
//汉子妹子模型
//汉子是1到10000的属性编号,妹子是武器的编号1到1000000
using namespace std;
const int maxm=1e4+1,maxn=1e6+1;
int n,a,b,tot,now,head[maxm],vis[maxn],match[maxn];
struct edge
{
int to,next;
}e[maxn<<1];//乘2
inline void add(int f,int t)//链式前向星
{
e[++tot].to=t;
e[tot].next=head[f];
head[f]=tot;
}
inline int read()//读入优化
{
char ch;int x=0,f=1;
while(!isdigit(ch=getchar())){(ch=='-')&&(f=-f);}
while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
}
inline int dfs(int x)//匈牙利算法给每一个男孩子匹配妹子,给每一个属性匹配一把枪
{
for(int i=head[x];i;i=e[i].next)
{
if(vis[e[i].to]==now)continue;
vis[e[i].to]=now;
if(!match[e[i].to]||dfs(match[e[i].to]))
{
match[e[i].to]=x;
return 1;
}
}
return 0;
}
int main()
{
ios::sync_with_stdio(0);
n=read();
for(int i=1;i<=n;i++)
{
a=read(),b=read();
add(a,i),add(b,i);//属性是汉子,武器的编号是妹子,建边,单向
}
for(int i=1;i<=10001;i++)
{
now=i;
if(!dfs(i))//当我们某一次无法匹配属性点i的时候,我们就得到了答案i-1
{
cout<<i-1<<endl;
return 0;
}
}
return 0;
}
II: upper and thinking the same, but different codes wind, a reattachment
#include <bits/stdc++.h>
using namespace std;
const int maxm=1e4+1,maxn=1e6+1;
int first[maxm],book[maxn],match[maxn],n,tot,id,o;
struct edge
{
int to,nex;
}e[maxn<<1];
inline void add(int f,int t)
{
e[++tot].to=t;
e[tot].nex=first[f];
first[f]=tot;
}
inline bool dfs(int x)
{
//first[i]初始值为-1,所以i+1,0时不运行
for(int i=first[x],v;i+1;i=e[i].nex)
{
if(book[v=e[i].to]-id)
{
book[v]=id;
if(!match[v]||dfs(match[v]))
{
match[v]=x;
return true;
}
}
}
return false;
}
inline int contin()
{
int ans=0;
for(int i=id=1;i<=10000;i++,id++)
{
if(dfs(i))ans++;
else break;
}
return ans;
}
int main()
{
ios::sync_with_stdio(0);
scanf("%d",&n);
memset(first,-1,sizeof(first));
for(int i=1;i<=n;i++)
for(int j=0;j<2;j++)scanf("%d",&o),add(o,i);
printf("%d\n",contin());
return 0;
}