二分匹配好博客:http://blog.csdn.net/xu3737284/article/details/8973720,https://www.byvoid.com/blog/hungary
http://blog.csdn.net/thundermrbird/article/details/52231639,http://dsqiu.iteye.com/blog/1689505
匈牙利算法可以解決的圖的問題:(二分圖)
1.圖的最小點覆蓋數 = 圖的最大匹配數;
2.圖的最大點獨立集 = 圖頂點數 - 圖的最大匹配數;
3.圖的最小路徑覆蓋數 = 原圖的頂點數 - 原圖拆點後形成的二部圖的最大匹配數/2;(無向無環圖)
4.圖的最小路徑覆蓋數 = 原圖的頂點數 - 最大匹配數;(有向無環圖)
無向無環圖的最小路徑覆蓋:拆成兩個點i1和i2,比如i和j連,拆後變成i1--〉j2,j1--〉i2
二分匹配一題,最大匹配
題目:hdu 4160
題意:給定一些長方體,小的長方體可以放進大的長方體,而且保證輸入一定是按照長、寬、高進行輸入,保證長大於長,寬大於寬,高大於高才能放入,求最後能剩幾個長方體可見
題解:最小路徑覆蓋,求最大匹配(匈牙利算法o(n*e))
代碼:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;
//const int N=600;
typedef struct
{
int a,b,c;
}Node;
Node node[600];
int head[600*2];
typedef struct
{
int to,next;
}Edge;
Edge edge[600*600];
int match[600*2];
bool vis[600*2];
bool dfs(int root)
{
for(int i=head[root];i!=-1;i=edge[i].next)
{
int v=edge[i].to;
if(!vis[v])
{
vis[v]=1;
if(match[v]==-1 ||dfs(match[v]))
{
match[v]=root;
return true;
}
}
}
return false;
}
int main()
{
int n;
while(~scanf("%d",&n) && n)
{
for(int i=1;i<=n;i++)
{
scanf("%d %d %d",&node[i].a,&node[i].b,&node[i].c);
}
int cnt=1;
memset(head,-1,sizeof(head));
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(node[i].a<node[j].a && node[i].b<node[j].b && node[i].c<node[j].c)
{
edge[cnt].to=j+600;//注意這,要將兩個分開,當成兩個點,唯一的改變點
edge[cnt].next=head[i];
head[i]=cnt++;
}
}
}
int ans=0;
memset(match,-1,sizeof(match));
for(int i=1;i<=n;i++)
{
memset(vis,0,sizeof(vis));
ans+=dfs(i);
}
printf("%d\n",n-ans);
}
return 0;
}
待續........