图论 —— 二分图的判定及最大匹配
Posted op-z
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了图论 —— 二分图的判定及最大匹配相关的知识,希望对你有一定的参考价值。
二分图:可将图中顶点分为两个集合,集合内元素独立。
判定:至少有两个顶点,若有回路,长度必为偶数。
染色法判定:从某点开始染色为x(-1或1),遍历其所有相邻节点,若未染色,染为-x,否则判断该点颜色,若为x,该图非二分图,退出;为-X则继续遍历。
UVA - 10004 Bicoloring
#include<iostream> #include<cstdio> #include<cstdlib> #include<cmath> #include<algorithm> #include<string> #include<cstring> #include<map> #include<stack> #include<set> #include<queue> using namespace std; typedef long long ll; #define me(x) memset(x, -1, sizeof(x)) #define mem(x) memset(x, 0, sizeof(x)) const int MOD = 1e18; const int N = 2e5 + 5; struct node int to, next, w; e[N]; //链式前向星存图 int head[N]; int vis[N]; int n, m, id, f; void ini() id=0; f=0; me(head); mem(vis); void add(int u, int v) e[id].to = v; e[id].next = head[u]; head[u] = id++; void bfs(int x) queue<int> q; q.push(x); vis[x]=-1; while(q.size()) x=q.front(); q.pop(); for(int i=head[x]; ~i; i=e[i].next) if(!vis[e[i].to]) q.push(e[i].to); vis[e[i].to]=-vis[x]; else if(vis[e[i].to] == vis[x]) f=1;break; if(f) break; return ; int main() int i, j, k; int t; while(~scanf("%d", &n)) if(!n) return 0; ini(); int u, v; scanf("%d", &m); for(i=0; i<m; i++) scanf("%d%d", &u, &v); add(u,v);add(v,u); bfs(0); if(f) printf("NOT BICOLORABLE.\n"); else printf("BICOLORABLE.\n"); return 0;
匹配:边集,集合内的边无公共顶点
最大匹配:二分图中的最大匹配数,即最大无公共顶点边集。
增广路:从未匹配边开始,沿未匹配边--匹配边--未匹配边--匹配边--未匹配边--的交替路
以非匹配边结束,则沿该增广路走匹配数加1
匈牙利算法思想:一直找增广路,增加匹配数,无增广路时匹配数达到最大
POJ - 1469 COURSES
#include<iostream> #include<cstdio> #include<cstdlib> #include<cmath> #include<cstring> #include<string> #include<algorithm> #include<map> #include<queue> #include<stack> #include<list> #include<set> using namespace std; typedef int ll; typedef pair<ll,ll> P; typedef long double ld; #define mem(x) memset(x, 0, sizeof(x)) #define me(x) memset(x, -1, sizeof(x)) #define fo(i,n) for(i=0; i<n; i++) #define sc(x) scanf("%d", &x) #define sca(n,m) scanf("%d%d", &n, &m) #define pr(x) printf("%d\n", x) #define pri(x) printf("%d ", x) #define lowbit(x) x&-x const ll MOD = 1e9 + 7; const ll oo = 1e18; const ll N = 3e3 + 5; vector<ll> ve[N]; ll vis[N], cy[N]; ll dfs(ll u) for(ll i=0; i<ve[u].size(); i++) if(!vis[ve[u][i]]) vis[ve[u][i]]=1; if(!cy[ve[u][i]] || dfs(cy[ve[u][i]])) //找增广路 cy[ve[u][i]]=u; return 1; return 0; int main() ll i, j, k; ll n, m, t; ll x; sc(t); while(t--) sca(n,m); for(i=m+1; i<=m+n; i++) ve[i].clear(); mem(cy); for(i=m+1; i<=n+m; i++) sc(k); for(j=0; j<k; j++) sc(x),ve[i].push_back(x); ll ans=0; for(i=m+1; i<=n+m; i++) for(j=1; j<=m; j++) vis[j]=0; if(dfs(i)) ans++; if(ans==n) printf("YES\n"); else printf("NO\n"); return 0;
以上是关于图论 —— 二分图的判定及最大匹配的主要内容,如果未能解决你的问题,请参考以下文章
图论二分图的应用(染色法判断二分图,最大匹配,最小点覆盖,最大独立集,最小路径点覆盖,最小路径重复点覆盖)