摘要:
题意: 给n个黑点和n个白点的坐标,然后连n条线段连接黑点和白点,使得所有线段不相交,求匹配方案。解法: 白书上的例题,建图思路蛮好的。 二分图,黑点和白点在两个集合里。然后求最小匹配,这样的结果肯定保证线段不相交。为什么呢? 因为不存在三点共线,所以对于两条线段来说,如果他们相交了,我们可以交换一下匹配的点使得四个点构成两条不相交的线,这样结果肯定要变小,画个图就知道了。p.s.貌似卡精度??被卡爆了。。。 1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include< 阅读全文
摘要:
题意: 给定n*n的矩阵,每个格子有个值s[i][j],现在要求对每行和每列各分配一个值,r[i],c[i]使得对所有的格子都有s[i][j]<=r[i]+c[j]成立,并且sum{r[i]}+sum{c[i]}尽量小。解法: 最近在做各种匹配,看到那个不等式,很容易联想到KM算法中那个lx[i]+ly[j]>=w[i][j],在KM结束之后,所有顶标之和是最小的。 想一下KM的思想,就是通过修改顶标的值来使得尽量多的边满足lx[i]+ly[j]==w[i][j],因为这样的边才会进入相等子图。而在算法结束后,所有的点都已经完成了匹配,也就是对于每对匹配点i,j,lx[i]+ly[ 阅读全文
摘要:
解法: 二分图的模型显而易见,而且对于一个不含孤立点的二分图,最小点覆盖数=最大匹配数。问题要求输出一个最小点覆盖集,我们可以在求出最大匹配之后,以未覆盖的x点进行标记,沿着未覆盖->覆盖->未覆盖->覆盖...的路径标记,最后x中未标记的和y中标记的点构成最小点覆盖集。具体的讲解可以看这个p.s.代码写的太丑了~~~~(>_<)~~~~ 1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<map> 5 #define N 1 阅读全文
摘要:
题意: 给定一个有向图,把图分成一些环,要求每个点只属于一个环,求满足条件的环所有边权和的最小值。解法: 对于满足条件的环,每个点的入度和出度均为1,我们可以把每个点拆成入点和出点,那么也就是说一个入点对应一个出点,反之亦然,那么这个问题就变成了一个二分图匹配问题,因为要取最小值,我们可以把每条边的权值取相反数,然后求一次最优匹配,对求得的结果再取相反数即为答案。 1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #define N 110 5 using namespace std 阅读全文
摘要:
这两天学习了一下2-SAT,主要参考了以下两个资料: 《由对称性解2-SAT问题》 《2-SAT解法浅析》 另外还有这个博客我觉得讲得挺白话的。建图: 2-SAT问题远没有网络流那样复杂,只要抓住关系建好图基本就直接可以解了,在这类问题中建边的规则就是“必须”,对于边<i,j>,它的意义就是选择了i就必须选j。 对于题目中给出的每对关系都可以化成下面的几种形式: A,B不能同时取 <A,B'><B,A'> A,B不能都不取 <A',B><B',A> A,B必须都取或者都不取 <A,B>< 阅读全文
摘要:
p.s.这场比赛题目都还挺好的我觉得,但还是做跪了,要是没那4个hack的话就死了...A.略B.解法:可以直接预处理出来距离每个数最近的素数,然后加一遍。当然也可以打个素数表然后二分。我的二分写法 1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<iostream> 5 #define N 1000010 6 using namespace std; 7 bool p[N]; 8 int s[N]; 9 int x[1010][1010];10 int 阅读全文
摘要:
题意:...解法:树链剖分,对点进行重编号,这样的话线段树中点的信息就是树中点的信息。。。别的很常规。。。 1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #define N 30010 5 #define lson l,m,n<<1 6 #define rson m+1,r,n<<1|1 7 using namespace std; 8 const int inf=1<<30; 9 struct Edge{ 10 int u,v,next; 1 阅读全文
摘要:
题意:给一棵节点数不超过10000的树,有三种操作: 1.询问a,b路径上最大的边权; 2.修改第i条边的边权; 3.将a->b路径上所有边的边权取反。解法: spoj375加强版,将点映射到线段树之后,需要用线段树的成段更新来支持操作三,其余的和spoj那题做法一样。 1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #define N 10010 5 #define lson l,m,n<<1 6 #define rson m+1,r,n<<1|1 阅读全文
摘要:
题意:给一棵树,节点数不超过10000,有两个操作:1.询问a,b路径上最长的边长。2.把第a条边长度改为b.p.s.人生中第一个树链剖分,尼玛debug了好久好久我擦。。。分析:轻重边路径剖分,把点都映射到线段树上搞之。。。具体的东西等我刷一刷题之后一起写个总结吧o(╯□╰)o 1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<iostream> 5 #define N 10010 6 #define lson l,m,n<<1 7 #de 阅读全文
摘要:
题意:给定一棵n节点的树(n<=10000),求满足dis(i,j)<=k的点数个数。p.s.准备学习树链剖分。。先从qzc的论文开始。。解法:树上分治。 我们可以通过dfs求出每个点到子树根的距离,对于以u为根的子树,满足条件并且路径过u的点对数=满足条件的所有点对数-路径不过u的点对数。 求法就是对所有dis排序然后两个指针扫,时间复杂度O(n).和http://acm.buaa.edu.cn:4567/problems/25一样的做法。 当树退化的时候直接分治复杂度会很高,所以对于每个子树我们要找出重心,然后选重心为根再进行分治。这样的话递归深度会控制在log(n). 1 # 阅读全文