染色配对(详解+代码)
来源:互联网 发布:老虎证券 财报数据 编辑:程序博客网 时间:2024/05/02 12:04
Description
(说实话我也不知道这图片是什么)
Solution
然而在这里我还是比较有必要讲一下题意的
定义一种东西叫团,可以看作每个团都是一个完全图
定义极大团是指没有比自己更大的团包含自己
给你
求这个图的极大匹配(就是两两点连边,每个点最多是一条边的端点)个数及匹配方案(任意输出)
因为这个图并没有直接给出点与点之间的关系,所以我们不妨把每个极大团设为一个大点(为了区分,我们把新图中的点也就是原来的极大团称为大点,原图中的点称为小点),由于每个小点都是属于刚好两个极大团的,所以小点就是新图中的边
显然,一个极大团中的小点都是可以两两匹配的。
设
对于新图中的每一个联通块,我们都做一个DFS,对于每个联通块组成的搜索树
(边上是边的编号,也就是小点的编号)
极大匹配小点也就是极大匹配两条相邻的边
从底部回溯上来时,我们看这个大点还有多少条边(
如果是偶数,那就两两匹配
如果是奇数,那就把多出来的那一个留给他父亲,让他父亲来选择匹配
自己在图上模拟一下……就容易理解了
注意每匹配一条边相应
可以发现一个奇妙的性质
对于新图每一个联通块,它的极大匹配个数就是联通块
因为每一个点都可以推给他父亲
Code
#include<cstdio>#include<cstdlib>#include<algorithm>#include<iostream>#include<cstring>#include<cmath>#define fo(i,a,b) for(i=a;i<=b;i++)#define fod(i,a,b) for(i=a;i>=b;i--)using namespace std;struct note{ int x,y,z;};bool cmp(note x,note y){ return x.x<y.x;}int n,m,a1[20001][2],pr[100001][2],ans,size[20001];note pt[400002];bool bz[20001],b[200001];void match(int x,int y){ pr[++ans][0]=pt[x].z; pr[ans][1]=pt[y].z; b[pt[x].z]=1; b[pt[y].z]=1; size[pt[x].x]--; size[pt[x].y]--; size[pt[y].x]--; size[pt[y].y]--;}void find(int k,int f){ int i,j,sz=size[k]; bool bzl=1; if (a1[k][0]!=0) { i=a1[k][0]; while (i<=a1[k][1]&&(b[pt[i].z]||(pt[i].y==f&&sz%2!=0&&bzl))) { if (pt[i].y==f&&sz%2!=0&&bzl) bzl=0; i++; } j=i+1; while (j<=a1[k][1]) { while (j<=a1[k][1]&&(b[pt[j].z]||(pt[j].y==f&&sz%2!=0&&bzl))) { if (pt[j].y==f&&sz%2!=0&&bzl) bzl=0; j++; } if (j<=a1[k][1]) { match(i,j); } i=j+1; while (i<=a1[k][1]&&(b[pt[i].z]||(pt[i].y==f&&sz%2!=0&&bzl))) { if (pt[i].y==f&&sz%2!=0&&bzl) bzl=0; i++; } j=i+1; } }}void dfs(int k,int f){ int i; if (a1[k][0]!=0) { fo(i,a1[k][0],a1[k][1]) { if (bz[pt[i].y]==0) { bz[pt[i].y]=1; dfs(pt[i].y,k); } } } find(k,f);}int main(){ cin>>m>>n; int i; fo(i,1,n) { scanf("%d%d",&pt[2*i-1].x,&pt[2*i-1].y); pt[2*i-1].z=i; pt[2*i].x=pt[2*i-1].y; pt[2*i].y=pt[2*i-1].x; pt[2*i].z=i; } sort(pt+1,pt+2*n+1,cmp); fo(i,1,2*n) { size[pt[i].x]++; if (pt[i].x!=pt[i-1].x) { a1[pt[i-1].x][1]=i-1; a1[pt[i].x][0]=i; } } a1[pt[2*n].x][1]=2*n; ans=0; fo(i,1,m) { if (!bz[i]) { bz[i]=1; dfs(i,0); } } cout<<ans<<endl; fo(i,1,ans) { printf("%d %d\n",pr[i][0],pr[i][1]); }}
1 0
- 染色配对(详解+代码)
- 染色配对
- GDOI模拟 染色配对
- 【GDOI模拟】染色配对
- 【JZOJ4376】染色配对
- 【GDOI2016模拟3.9】染色配对
- 代码染色!
- 代码染色!
- JZOJ 4376【GDOI2016模拟3.9】染色配对
- 【bzoj 2243】【SDOI2011】染色 题解&代码(C++)
- 纯属利用代码染色功能
- BZOJ2243 [SDOI2011]染色 题解&代码
- 染色问题(Dye)
- 染色
- 染色
- 染色
- 数字配对(二分)
- 数组配对(算法)
- 按字母索引排序listview
- 自定义控件实践之Dialog
- Log4j – 如何配置多个logger
- Android API Guides---Drawable Resources
- Android应用正确的退出方式(单例模式)
- 染色配对(详解+代码)
- 用rz sz命令传输文件
- AVS、MPEG-2、H.264 标准文档
- codeforces 653F
- @RequestParam @RequestBody @PathVariable 等参数绑定注解详解
- CTF进阶之路1——virtualbox安装
- 不能选择设备(真机,模拟器都不可以)
- 每天进步一点点——Linux中的文件描述符与打开文件之间的关系
- 各位IT同胞,请注意!!!找工作需谨慎