HDU 3551 Hard Problem 一般图的最大匹配(带花树)
来源:互联网 发布:python 爬虫 伯乐在线 编辑:程序博客网 时间:2024/06/05 20:31
题目大意:给你一个图,让你取一个包含所有点和其中一些边的子图,使子图中每一点的度为给定的值。
建图很神。
把每条边(u,v)拆成两个点,x , y,并在 x,y间连一条边;
如果题目要求u点的度数为f[u],那么就把u拆成f[u]个点,每个点与x相连,
同样的,把v点拆成f[v]个点,每个点与y相连,
然后用带花树求最大匹配,如果达到完美匹配,就存在,否则不存在。
至于原理,
在最终的匹配方案中,如果达到完美匹配,
则每个点的每个度都匹且唯一匹配着一条边的一头,
如果想达到完美匹配,这条边的另一头必定匹配着另一个点的一个度,
这样一条边的匹配是合乎要求的。
而又由于完美匹配,每个度都被匹配上了,因此就满足题意了。
至于被删掉的边,
在最终的匹配方案中 ,他被拆成的两个点间进行匹配,
表示没与任意一个度相关连。
#include <iostream>#include <cstdio>#include <algorithm>#include <cstring>#include <cstdlib>#include <queue>#include <stack>using namespace std;#define REP(i,n) for(int i=0;i<(n);++i)#define FOR(i,l,r) for(int i=(l);i<=(r);++i)#define DSC(i,r,l) for(int i=(r);i>=(l);--i)#define N 1010#define SET(a,b) memset(a,b,sizeof(a))deque<int> Q;//g[i][j]存放关系图:i,j是否有边,match[i]存放i所匹配的点//建图开始初始化g//最终匹配方案为match//复杂度O(n^3)//点是从1到n的bool g[N][N],inque[N],inblossom[N];int match[N],pre[N],base[N];//找公共祖先int findancestor(int u,int v){ bool inpath[N]= {false}; while(1) { u=base[u]; inpath[u]=true; if(match[u]==-1)break; u=pre[match[u]]; } while(1) { v=base[v]; if(inpath[v])return v; v=pre[match[v]]; }}//压缩花void reset(int u,int anc){ while(u!=anc) { int v=match[u]; inblossom[base[u]]=1; inblossom[base[v]]=1; v=pre[v]; if(base[v]!=anc)pre[v]=match[u]; u=v; }}void contract(int u,int v,int n){ int anc=findancestor(u,v); SET(inblossom,0); reset(u,anc); reset(v,anc); if(base[u]!=anc)pre[u]=v; if(base[v]!=anc)pre[v]=u; for(int i=1; i<=n; i++) if(inblossom[base[i]]) { base[i]=anc; if(!inque[i]) { Q.push_back(i); inque[i]=1; } }}bool dfs(int S,int n){ for(int i=0; i<=n; i++)pre[i]=-1,inque[i]=0,base[i]=i; Q.clear(); Q.push_back(S); inque[S]=1; while(!Q.empty()) { int u=Q.front(); Q.pop_front(); for(int v=1; v<=n; v++) { if(g[u][v]&&base[v]!=base[u]&&match[u]!=v) { if(v==S||(match[v]!=-1&&pre[match[v]]!=-1))contract(u,v,n); else if(pre[v]==-1) { pre[v]=u; if(match[v]!=-1)Q.push_back(match[v]),inque[match[v]]=1; else { u=v; while(u!=-1) { v=pre[u]; int w=match[v]; match[u]=v; match[v]=u; u=w; } return true; } } } } } return false;}int solve(int n){ SET(match,-1); int ans=0; for(int i=1; i<=n; i++) if(match[i]==-1&&dfs(i,n)) ans++; return ans;}//往上是带花树模板,不用看int f[60];int x[210],y[210];int map[55][210];bool build(int n,int m){ int num=0; FOR(i,1,n) FOR(j,1,f[i]) map[i][j]=++num;//给i点的第j个度一个标号,方便接下来的建图 REP(i,m) { FOR(j,1,f[ x[i] ]) g[ map[ x[i] ][j] ][num+1]=g[num+1][ map[ x[i] ][j] ]=1; FOR(j,1,f[ y[i] ]) g[ map[ y[i] ][j] ][num+2]=g[num+2][ map[ y[i] ][j] ]=1; g[num+1][num+2]=g[num+2][num+1]=1; num+=2; }//把边被拆成的两个点分别与两头的每个度相连 if(solve(num)*2==num) return 1; return 0;}int main(){ //freopen("in","r",stdin); int cas,cas1=1,n,m; cin>>cas; while(cin>>n>>m) { memset(g,0,sizeof(g)); REP(i,m) scanf("%d%d",&x[i],&y[i]); FOR(i,1,n) scanf("%d",&f[i]); printf("Case %d: ",cas1++); if(build(n,m)) puts("YES"); else puts("NO"); } return 0;}
- HDU 3551 Hard Problem 一般图的最大匹配(带花树)
- hdu3551 Hard Problem 【一般图匹配】
- 【转】带花树(一般无向图的最大匹配)
- 【转】带花树(一般无向图的最大匹配)
- UOJ 一般图的最大匹配(带花树算法模板)
- 带花树(一般图最大匹配)
- 带花树模板(一般图最大匹配)
- hdu 4687 带花树求一般图最大匹配(模板)
- 带花树 一般图最大匹配
- 一般图最大匹配
- 一般图最大匹配
- UOJ-79 一般图的最大匹配(带花树模板求解)
- 利用带花树算法解决一般图的最大匹配
- 一般图的最大匹配问题(真心觉得难)
- 一般图最大匹配的匈牙利算法
- URAL1099-Work Scheduling(一般图最大匹配(带花树))
- 带花树(一般图最大匹配)详解 ZOJ 3316
- [模板]带花树算法(一般图最大匹配)
- String 和StringBuffer和StringBuilder区别
- JavaScript学习笔记(四十四) 装饰器
- openstack_note
- java jni 编程
- java中byte转换int时为何与0xff进行与运算
- HDU 3551 Hard Problem 一般图的最大匹配(带花树)
- 使用getNamedDispatcher()转发请求
- hdu 1568 Fibonacci 斐波那契通项公式求对数
- [LeetCode] Merge Sorted Array
- 高并发的epoll+多线程
- wikioi p1078 最小生成树
- LeetCode - Permutation Sequence
- 机房收费系统-- MDI子窗体显示技巧(续vb.net版)
- wikioi p1231 最优布线问题