二分图也就是给定关系,划分成两个集合,使得各自集合的元素没有关系连接!
在这里不深刻探讨如何实现,而是通过算法来进行学习,二分图是一类非常简单的问题
但是最重要的还是图论中匹配模型的构造,要注意二分图的构造还不是非常容易的
匈牙利算法
1 bool match(int x){ 2 for(int i=head[x];i;i=next[i]){ 3 int y=ver[i]; 4 if(!vis[y]){ 5 vis[y]=true; 6 if(!matched[y] || match(matched[y])){ 7 matched[y]=x; 8 return true; 9 } 10 } 11 } 12 return false; 13 }
注意每次进行match的时候需要将vis进行MEMSET
match->true匹配成功否则匹配失败
P1197 SCOI 2010 连续攻击游戏
1 #include <cstdio> 2 #include <cstring> 3 4 const int MAXN=(int)1e6+5,MAXM=(int)4e6+5; 5 int ver[MAXM],next[MAXM],head[MAXN],tot; 6 int matched[MAXN]; 7 bool vis[MAXN]; 8 9 void read(int &num){ 10 char c=getchar(); 11 num=0; 12 while(c<'0' || c>'9') c=getchar(); 13 while(c>='0' && c<='9') num=(num*10+c-'0'),c=getchar(); 14 } 15 16 void add(int u,int v){ 17 ver[++tot]=v; 18 next[tot]=head[u]; 19 head[u]=tot; 20 } 21 22 bool match(int x){ 23 for(int i=head[x];i;i=next[i]){ 24 int y=ver[i]; 25 if(!vis[y]){ 26 vis[y]=true; 27 if(!matched[y] || match(matched[y])){ 28 matched[y]=x; 29 return true; 30 } 31 } 32 } 33 return false; 34 } 35 36 int main(){ 37 int n,a,b; 38 scanf("%d",&n); 39 for(int i=1;i<=n;i++){ 40 read(a),read(b); 41 add(a,i),add(b,i); 42 } 43 int ans=0; 44 for(int i=1;i<=10000;i++){ 45 memset(vis,0,sizeof(vis)); 46 if(match(i)) ans++; 47 else break; 48 } 49 printf("%d",ans); 50 return 0; 51 }