水了个圈钱杯省一,不过估计国赛也拿不了奖,但还是小小挣扎一下。
什么是二分图:G=(V,E)是一个无向图,若顶点V可以分为两个互不相交的子集A,B,并图中的每一条边(i,j)所关联的ij属于不同的顶点集,那么G就是一个二分图。
如何判定?当前仅当图中不含有奇数环。
如果图中有奇数环,假如是一个三角形123,那么1,2一定在不同的集合,2,3一定在不同的集合,那么13就在同一个集合,矛盾。
对于充分性,黑白交替染色即可。
下面是AC代码:
#include<bits/stdc++.h>
using namespace std;
int n,m;
struct node{int u,next;
};
int head[100010],col[100010],cnt;
node edge[200020];
void merge(int u1,int v)
{edge[++cnt].u=v;edge[cnt].next=head[u1];head[u1]=cnt;
}
bool dfs(int ck,int colo)
{col[ck]=colo;for(int i=head[ck];i!=-1;i=edge[i].next){int coco=edge[i].u;if(col[coco]){if(col[coco]==colo) return 0;}else{if(dfs(coco,3-colo)==0) return 0;}}
}
int main()
{memset(head,-1,sizeof(head));cin>>n>>m;for(int i=1;i<=m;i++){int uu,vv;scanf("%d%d",&uu,&vv);merge(uu,vv);merge(vv,uu);}bool flag=1;for(int i=1;i<=n;i++){if(!col[i]){if(dfs(i,1)==0){flag=0;break;}}}if(flag==1) cout<<"Yes";else cout<<"No";
}
二分图的最大匹配:匈牙利算法
枚举一下左边的点,去右边找匹配,如果已经有了,那么看看被占的那个点有没有其他选择,于是就是一个递归,唯一不同就是那个点不能去访问,我们用st存是否访问过即可,下面是AC代码:
#include<bits/stdc++.h>
using namespace std;
int n1,n2,m;
struct node{int dian,next;
}edge[100010];
int head[600],cnt;
bool st[2000];
int match[2000];
void merge(int x,int y)
{edge[++cnt].dian=y;edge[cnt].next=head[x];head[x]=cnt;
}
bool find(int x)
{for(int i=head[x];i!=-1;i=edge[i].next){int ck=edge[i].dian;if(!st[ck]){st[ck]=1;if(match[ck]==0||find(match[ck])){match[ck]=x;return 1;}}}return 0;
}
int main()
{cin>>n1>>n2>>m;memset(head,-1,sizeof(head));while(m--){int u,v;scanf("%d%d",&u,&v);merge(u,v);}int res=0;for(int i=1;i<=n1;i++){memset(st,0,sizeof(st));if(find(i)) res++;}cout<<res;
}