URAL1099-Work Scheduling(一般图最大匹配(带花树))
来源:互联网 发布:淘宝怎么修改差评? 编辑:程序博客网 时间:2024/06/09 08:12
题目来源:https://et/problem/URAL-1099
题意
给出一个一般有向图,求最大匹配,并且把最大匹配的点数输出,以及匹配额点。。。
思路
最大匹配分为二分图最大匹配和一般图最大匹配,利用匈牙利算法或者HK算法可解,一般图最大匹配利用带花树算法可解(缩花,开花)(并查集证明是同一朵花,最近公共祖先找花。)
在增广路径的过程中,利用深搜的原理生成搜索树,假如称离根节点有偶数条边的点为偶点,称离根节点有奇数条边的点为奇点,那么假设已匹配点称为S,待匹配点称为T,也即是说偶点是S,奇点是T:
对于二分图来讲:
递归找到一个T,便可以增广路径,也即是S–>T(S可以到T),也就是偶点到奇点。
对于一个一般图来讲:
递归找到一个T,同样可以增广路径,但是他还有另外一种情况:偶点到偶点,也就是一个点出现两次,并且距离都是偶数条边,如果在这棵树上两个偶点连一条边,那么从树根到这两个偶点里面的任意一个点都可以是偶点(就成了花),也就是这一般图中,所覆盖的点可以整体看成一个偶点(缩花),利用并查集,以及LCA操作进行缩花,然后就会清除这种偶点到偶点的情况。。。
推荐博客:http://www.csie.ntnu.edu.tw/~u91029/
代码
//裸模板#include<cmath>#include<vector>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int maxn=230;int n;int pre[maxn];int finds(int x){ return pre[x]==x?x:pre[x]=finds(pre[x]);}void unit(int x,int y){ int fx=finds(x); int fy=finds(y); if(fx!=fy) pre[fx]=fy;}int match[maxn],nexx[maxn],vis[maxn],mark[maxn],Q[maxn],rear;int LCA(int x,int y){ static int t=0;t++; while(1) { if(x!=-1) { x=finds(x); if(vis[x]==t)//如果把t直接改成1,就会超时。。不知道是为啥 return x; vis[x]=t; if(match[x]!=-1) x=nexx[match[x]]; else x=-1; } swap(x,y); }}void group(int x,int y){ while(x!=y) { int a=match[x],b=nexx[a]; if(finds(b)!=y) nexx[b]=a; if(mark[a]==2) mark[Q[++rear]=a]=1; if(mark[b]==2) mark[Q[++rear]=b]=1; unit(x,a); unit(a,b); x=b; }}vector<int> v[maxn];void ex_load(int s){ memset(vis,0,sizeof(vis)); memset(mark,0,sizeof(mark)); memset(nexx,-1,sizeof(nexx)); for(int i=1;i<=n;i++) pre[i]=i; mark[s]=1; Q[0]=s,rear=0; for(int front=0;match[s]==-1&&front<=rear;front++) { int x=Q[front]; for(int i=0;i<(int)v[x].size();i++) { int y=v[x][i]; if(match[x]==y) continue; if(finds(x)==finds(y)) continue; if(mark[y]==2) continue; if(mark[y]==1) { int r=LCA(x,y); if(finds(x)!=r) nexx[x]=y; if(finds(y)!=r) nexx[y]=x; group(x,r); group(y,r); } else if(match[y]==-1) { nexx[y]=x; int u=y; while(u!=-1) { int v=nexx[u]; int tmp=match[v]; match[u]=v,match[v]=u; u=tmp; } break; } else { nexx[y]=x; mark[Q[++rear]=match[y]]=1; mark[y]=2; } } }}bool g[maxn][maxn];int main(){ scanf("%d",&n); memset(g,0,sizeof(g)); int x,y; while(~scanf("%d%d",&x,&y)) { if(x!=y&&!g[x][y]) { v[x].push_back(y); v[y].push_back(x); g[x][y]=g[y][x]=1; } } memset(match,-1,sizeof(match)); for(int i=1;i<=n;i++) { if(match[i]==-1) ex_load(i); } int ans=0; for(int i=1;i<=n;i++) { if(match[i]!=-1) ans++; } printf("%d\n",ans); for(int i=1;i<=n;i++) { if(match[i]>i) { printf("%d %d\n",i,match[i]); } } return 0;}
阅读全文
0 0
- URAL1099-Work Scheduling(一般图最大匹配(带花树))
- URAL1099. Work Scheduling(一般图匹配带花树开花算法)
- URAL1099:Work Scheduling(任意图匹配,带花树)
- URAL 1099 Work Scheduling(一般图匹配 带花树算法)
- URAL 1099 Work Scheduling(一般图匹配模板)
- URAL 1099. Work Scheduling 一般图匹配带花树
- URAL 1099. Work Scheduling 一般图匹配模板题
- 带花树(一般图最大匹配)
- 带花树模板(一般图最大匹配)
- URAL 1099 Work Scheduling(带花树)
- 【转】带花树(一般无向图的最大匹配)
- 【转】带花树(一般无向图的最大匹配)
- 带花树(一般图最大匹配)详解 ZOJ 3316
- UOJ 一般图的最大匹配(带花树算法模板)
- [模板]带花树算法(一般图最大匹配)
- #79. 一般图最大匹配(带花树算法)
- 带花树 一般图最大匹配
- 一般图最大匹配
- JAVA下实现二叉树的先序、中序、后序、层序遍历(递归和循环)
- O
- 为什么AI人才这么贵、需求这么迫切?因为用对他们真的能改变一个行业!
- 常量变量以及循环
- pip超时问题(timeout)的解决方法
- URAL1099-Work Scheduling(一般图最大匹配(带花树))
- zabbix客户端批量配置snmp
- 数制转换
- 9款大气实用的HTML5/CSS3注册登录表单
- css01-初识
- JSP 开发之THE SERVLET NAME ALREADY EXISTS.解决方法
- Unity3d UGUI屏幕自适应(多分配率适配)
- Firefly的人脸技术
- Linux下软件安装的几种方式