二分图:可将图中顶点分为两个集合,集合内元素独立。
判定:至少有两个顶点,若有回路,长度必为偶数。
染色法判定:从某点开始染色为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. "); else printf("BICOLORABLE. "); } 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 ", 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 "); else printf("NO "); } return 0; }