【GDOI模拟】染色配对
2016-04-10 00:51
405 查看
Description
Solution
比赛的时候没有时间打这一题了。回想一下才发现,是我昨天才做过的原题的类型题。
小N研究的NP完全问题jzoj上面叫A……
其实题意是在一个图中出最多的边,并且他们没有交集。
因为每一个点只会在匹配中最多出现一次,那么我们就要选择这些点都要选哪一些极大团。
我们一开始先让这些点随便选极大团,然后要他们可以选的两个极大团互相两边,表示这个点可以从这个极大团转移到另一个去,一条边也可以表示成一个点。
给极大团连完边之后,就会发现联通块的最大匹配的答案为边数除以2,因为两两的点要连边。
然后第一个答案就很好解了。
对于第二些答案,与小N研究的NP完全问题的做法极像。
因为有一些极大团中会有奇数个点,这样就不能匹配完,那么我们需要把这些点给转移走,那么我们就要考虑,每个点是要在那个极大团中进行匹配。
搜出一棵dfs树之后,如果某个节点i的子树的奇数节点的和是奇数,那么节点i就需要向上转移走一个点了,那么就是他与上面连接的这条边表示的节点选择上面的极大团,否则选择方向不变。
当极大团中的点确定之后,随意两两匹配就可以了。
Code
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #define fo(i,a,b) for(i=a;i<=b;i++) const int maxn=200007; using namespace std; int i,j,k,l,t,n,m,ans; int first[maxn*2],next[maxn*2],last[maxn*2],num,shu[maxn*2]; int a[maxn*2],b[maxn*2],c[maxn*2],d[maxn*2],tot,ans1[maxn][2]; bool bz[maxn]; void add(int x,int y,int z){ last[++num]=y; next[num]=first[x]; first[x]=num; shu[num]=z; } void add1(int x,int y){ last[++num]=y; next[num]=first[x]; first[x]=num; } int dfs(int x){ int i,j=c[x]%2,k; bz[x]=1; for(i=first[x];i;i=next[i]){ if(!bz[last[i]]){ k=dfs(last[i]); d[shu[i]]=k%2; j+=k; } } return j; } int dfs1(int x){ int i,j=0; bz[x]=1; for(i=first[x];i;i=next[i]){ if(!bz[last[i]]){ j+=dfs1(last[i])+1; } else j++; } return j; } int main(){ scanf("%d%d",&n,&m); fo(i,1,m){ scanf("%d%d",&a[i],&b[i]); c[a[i]]++; } fo(i,1,m){ add(a[i],b[i],i); add(b[i],a[i],i); } fo(i,1,n){ if(!bz[i])ans+=dfs1(i)/4;//这里是处理了双向边 } printf("%d\n",ans); memset(bz,0,sizeof(bz)); fo(i,1,n){ if(!bz[i])t=dfs(i); } t=0; memset(first,0,sizeof(first));num=0; fo(i,1,m){ if(d[i]%2==0){ add1(a[i],i); } else{ add1(b[i],i); } } fo(i,1,n){ int u=0; for(j=first[i];j;j=next[j]){ u=last[j]; j=next[j]; if(!j)break; printf("%d %d\n",u,last[j]); } } }
相关文章推荐
- ORA-00257: archiver error. Connect internal only, until freed
- 【leetcode】2. Add Two Numbers
- IOS Animation-CABasicAnimation、CAKeyframeAnimation详解&区别&联系
- Semaphore and Mutex usages and differences
- CString字符串分割
- 10021---Compose and Model the Merchandise Shop
- 利用 padding+background & border 为图片设置双边框
- 什么是泛型
- 华为 字符集合
- VS2013设置护眼背景颜色
- 机器人走方格
- 算法练习Ip地址与整数的互相转换ipstrToint
- VMware虚拟机中red hat linux ping不通宿主物理主机原因
- 查看PHP代码执行的时间
- 堆排序:动态数组求中位数
- AS中import module、import project
- 协程 [wiki]
- codeforces 660C (尺取法 水~)
- 说说JSON和JSONP,也许你会豁然开朗
- android:ToolBar详解(手把手教程)