二分圖匹配([洛谷]P3386 模板 二分圖匹配)
阿新 • • 發佈:2017-12-02
markdown turn false code str 需要 return eof 位置
二分圖匹配其實十分簡單,原理只有一個,能換則換,騰出這個妹子的位置,不要考慮其他人是不是很不滿意從他喜歡中最喜歡的那一個變成了他喜歡中的最不喜歡的那一個,知道了這個原理,n遍DFS就可以過了:
#include<stdio.h> #include<string.h> const int Inf=1e9+10,maxn=5010,maxm=5010,maxe=10010; int gi(){ int sum=0,f=1;char ch=getchar(); while(ch>'9' || ch<'0'){if(ch=='-')f=-1;ch=getchar();} while(ch<='9' && ch>='0'){sum=sum*10+ch-'0';ch=getchar();} return sum*f; } struct node{ int to,next; }e[maxe]; int cnt,front[maxn],use[maxn]; int used[maxm],b[maxm],n,m; void Add(int u,int v){ e[++cnt].to=v; e[cnt].next=front[u]; front[u]=cnt; } bool dfs(int u){//尋找增廣路 for(int i=front[u];i;i=e[i].next) if(!used[e[i].to]){ used[e[i].to]=1; if(b[e[i].to]==0 || dfs(b[e[i].to])){ use[u]=e[i].to; b[e[i].to]=u; return true; } } return false; } int ED(){ int ans=0; for(int i=1;i<=n;i++) if(!use[i]){ memset(used,0,sizeof(used)); if(dfs(i))ans++; } return ans; } int main(){ int i,j,k,e; scanf("%d%d%d",&n,&m,&e); for(i=1;i<=e;i++){ int u=gi(),v=gi(); if(u<=n && v<=m)Add(u,v); } printf("%d\n",ED()); return 0; }
以上為鄰接表版本,如果有需要的,以下是鄰接矩陣版本
#include<stdio.h> #include<stdlib.h> #include<string.h> #include<math.h> #include<algorithm> using namespace std; int n,m; int g[1010][1010]; int flag[1010],b[1010]; bool dfs(int u); int ED(); void init(); int main(){ init(); return 0; } void init(){ int i,j,k,e; scanf("%d%d%d",&n,&m,&e); for(i=1;i<=e;i++){ int u,v; scanf("%d%d",&u,&v); if(u>n || v>m)continue; g[u][v]=1; } printf("%d\n",ED()); } int ED(){ int ans=0; for(int i=1;i<=n;i++){ memset(flag,0,sizeof(flag)); if(dfs(i))ans++; } return ans; } bool dfs(int u){ for(int v=1;v<=m;v++) if(g[u][v] && !flag[v]){ flag[v]=1; if(!b[v] || dfs(b[v])){ b[v]=u; return true; } } return false; }
二分圖匹配([洛谷]P3386 模板 二分圖匹配)