03 2012 档案
摘要:不会sap,邻接矩阵过。#include <cstdlib>#include <cstring>#include <cstdio> #include <queue>#define MAXN 375#define INF 0x3f3f3f3fusing namespace std;int cap[MAXN+1][MAXN+1], flow[MAXN+1][MAXN+1], N;int p[MAXN+1], c[MAXN+1];int seq[25][15], maxflow;inline void init(){ maxflow = 0; mems
阅读全文
摘要:简单二分匹配。代码如下:#include <cstring>#include <cstdlib>#include <cstdio>#define MAXN 205using namespace std;int N, M, G[MAXN][MAXN];int visit[MAXN], marry[MAXN];int path(int u){ for (int i = 1; i <= M; ++i) { if (!G[u][i] || visit[i]) { continue; } visit[i] = 1; if...
阅读全文
摘要:由于没有输出交换多少次,贡献了无数次 system error。求解该题相当与给每一行找到一个1对应出现的位置,在排序就可以了。代码如下:#include <cstdlib>#include <cstring>#include <cstdio>#include <cstring>#define MAXN 105using namespace std;int N, G[MAXN][MAXN], marry[MAXN], visit[MAXN];int r1[MAXN], r2[MAXN], count;int path(int u){ for (i
阅读全文
摘要:这题就是给定若干关系,求一个集合,该机和内部的各点之间没有任何关系,求得这个集合的元素最多为多少。代码如下:#include <cstdlib>#include <cstring>#include <cstdio>#define MAXN 500using namespace std;int N, visit[MAXN], marry[MAXN], G[MAXN][MAXN];int path(int u){ for (int i = 0; i < N; ++i) { if (!G[u][i] || visit[i]) { continue; ...
阅读全文
摘要:对于一个有向无环图,其最小简单路径覆盖就是等于节点数减去二分图的最大匹配数,对于每条弧,弧头作为X部,弧尾作为Y部。最后在求得最大匹配的基础上,没有被匹配的Y部的点就是简单路径的起点。其个数刚好就是节点数减去二分图的最大匹配数。证明略。代码如下:#include <cstring>#include <cstdlib>#include <cstdio>#define MAXN 125using namespace std;int N, M, G[MAXN][MAXN], marry[MAXN], visit[MAXN];int path(int u){ for
阅读全文
摘要:该题是经典的二分图匹配的应用,题义是这样的。给定K个工作,有两台机器,A机器有N种工作状态,B机器有M种工作状态,对于每一个工作,既可以被A完成又可以被B完成,求完成所有工作至少需要转换多少次模式。将A以及B的不同模式作为二分图的两个部分,工作作为边,则该题转化为求解最小顶点覆盖来求解。最小顶点覆盖:包含二分图的X,Y部的部分顶点的一个集合,使得所有的边至少有一个顶点在该点集内。最小顶点覆盖就等于二分图的最大匹配。证明如下:设二分图的最大匹配数为M(下图中M等于2),现假设下面的二分图只有 (A,a)以及(C,c)两条边,我们通过增加边来还原至原本的图。这个增加边的过程是不能够使得二分图的匹配
阅读全文
摘要:简单二分匹配代码如下:#include <stdio.h>#include <string.h>#define MAXN 100int G[MAXN][305], N;int marry[305], visit[305];int path(int u){ for (int i = 1; i <= N; ++i) { if (!G[u][i] || visit[i]) continue; visit[i] = 1; if (!marry[i] || path(marry[i])) { marry[i] =...
阅读全文
摘要:二部图(也叫二分图)概念:1.何为二部图 如果V(G)可以分到两个集合X,Y中,且X和Y内部没有G的边.那么图G就是一个二部图(等价于图G是可二顶点着色的)下图便是一个二部图. 2.二部图的性质 一个图是二部图当且仅当图G中没有奇环.比如说一个三角形就不可能分成两个部分,并且每个部分内部没有边,但一个正方形就可以.3.如何得到二部图的每个部分 任意选一个顶点,所有到该点距离为偶数的点构成的集合便是G中的一部分,距离为奇数的点为另一部分4.何为匹配 图G的一个匹配是一组没有公共端点的边构成的集合,如(图一)两条黑色的边构成一个大小为2的匹配,三条红色的边构成一个大小为3的匹配.图中的最...
阅读全文
摘要:还记得杭电的“骨牌铺方格”吗,这题可以说是它的强化板了。但是思路是一样的,就是通过得到前面的解来递推后面的结果。由于是一个较大的平面,较之杭电那题在行数和列数上都有了较多的组合情况,因此状态压缩有了用武之地。这题的一个难点就是如何用0,1来表示摆放的规律,参看别人的想法后,找到的这种方法虽然时间开销相对大了点,但是思路非常好理解。对于每一个格子,只有0,1两种状态,0代表没有放置,1代表放置。对于每一行的状态,1的含义会因为上一行的对应项而不同,如果与之对应的上一行的列为0的话,那么这个1代表这里放置了一个竖直的块,如果上一列是1的话那么两行都必须是横着放置的。2411Accepted328K
阅读全文
摘要:该题题义为有一只青蛙要过河,这条和有一个宽度,河中间有若干块石头,青蛙要求在m步的限制下跳跃到河对岸去,问在何种情况下,青蛙能够跳跃到河对岸,并且该方案中跳跃最远的一步数值最小(意思是说这种方案下对青蛙的跳跃能力的要求是最低的)。我们用二分答案的方式来解决这道题,其值可能存在的区间为 0到河的宽度L,对于这个区间中的某一个值,通过已知石头的分布来评价这个方案是否较优,那就是确定了跳跃的最大的距离,那么就让这只青蛙的允许的情况下,跳跃尽可能多的石头。再确定是否在规定的步数中跳到了对岸。代码如下:#include <cstring>#include <cstdlib>#in
阅读全文
摘要:这题相对于前面的little kings 来说简单了一些,没有了步数的限制,dp方程也简洁了不少。只需要考虑当前状态是否与上一个状态冲突即可。代码如下:#include <cstdio>#include <cstring>#include <cstdlib>#include <iostream>#define MAXN 20000using namespace std;long long f[25][MAXN];int N, M, map[25][25], s[MAXN];inline long long max(long long &x
阅读全文
摘要:这算是八皇后问题的变种了,普通的组合数学已经很难一下子将他求出来了,除此之外,我们用纯模拟来处理该题。 给定是一个N*N的矩阵,要求在这个图中放置K个点,这些点不能够相邻(包括上下左右以及对角线上的区域),用模拟如何来过这一题呢,那就是要推出动态递归方程,F[i][s][k] 代表第i行处于第s个状态且到目前行共下了k个棋子的总方案数,c[s]代表针对s这个状态有多少个1,有动态方程:F[i][s][k] = sum{ F[i-1][s'][k-c[s]],其中 s 与 s' 为不冲突的方案数 } 该方程的含义为 F[i][s][k] 中剩余的棋子数 k-c[s] 在上一行截止
阅读全文
摘要:题义就是在给定的图中判定是否存在欧拉回路。图G的一个回路,若它恰通过G中每条边一次,则称该回路为欧拉(Euler)回路。具有欧拉回路的图称为欧拉图(简称E图)。这里总结下各种图的判定的方法:1.无向图中:所给定的图为连通图,且所有节点的度为偶数;2.有向图中:所给定的图为连通图,且所有节点的度为零。代码如下:#include <cstdlib>#include <cstring>#include <cstdio>#define MAXN 1010using namespace std;int cnt[MAXN], set[MAXN]; int find(in
阅读全文
摘要:图的作用图是一种表示工具,改变问题的描述方式,往往是创造性的启发式解决问题的手段.一种描述方式就好比我们站在一个位置和角度观察目标,有的东西被遮挡住了,但如果换一个位置和角度,原来隐藏着的东西就可能被发现.采用一种新的描述方式,可能会产生新思想.图论中的图提供了一种直观,清晰表达已知信息的方式.它有时就像小学数学应用题中的线段图一样,能使我们用语言描述时未显示的或不易观察到的特征、关系,直观地呈现在我们面前,帮助我们分析和思考问题,激发我们的灵感.
阅读全文
摘要:题中定义了什么叫做可见线段。所谓可见线段就是在给定的垂直与x轴的直线中,能够在两个直线之间连接一条平行线,并且这条平行线不与任何其他的直线相交。WA一次,就是因为没有考虑到在建立点树的过程中会出现将 [1, 2] 和 [3, 4] 视为一条连接的直线,所以最后给坐标乘以一个2.代码如下:#include <cstdio>#include <cstring>#include <cstdlib>#include <algorithm>#include <vector>#include <map>#define MAXN 800
阅读全文
摘要:http://poj.org/problem?id=3667经典线段树,不解释了。代码如下:#include <cstdlib>#include <cstring>#include <cstdio> #include <algorithm>#define MAXN 50000 using namespace std;struct{ int l, r; int lmax, rmax, max, cover;}seg[MAXN*4];void build(int f, int l, int r){ int mid = l+r >> 1;
阅读全文
摘要:题目大意为给定一段内存快,要求根据命令输出正确的答案。New x 申请长度为x的空白内存的首地址,如果不满足输出Reject NewFree x 释放包含x节点的内存块,注意该内存块为一个New操作所确定的区域,即不必要将物理相邻的内存块视作一个内存块Get x 得到从左到右的第x个内存块Reset 重置总区间针对这些要求,设定一棵线段树,每个节点保留左,右连续空白段,以及区间总长。这样便能够处理New命令,而Free以及Get命令则用vector保留,用二分搜索优化。代码如下:View Code #include <cstdio>#include <cstring>#
阅读全文
摘要:前面还一位这是一道最长上升子序列的题目,只觉得无从下手,后来得知是最长连续上升子序列,于是有了想法。 (英文不好啊,题目中就能看出来的)对于每一个节点保留其左起及右起连续子序列长度和整个区间的最长连续长度。当然利用这三个信息加之线段树的结构我们就能够得到所要的结果。先说说我自己的写法(后来证明是写复杂了),对于每个询问我定义了三个状态 0, 1, 2。 0 表示该区间内不需要从左边或者是右边开始计算,1 表示求这段区间的右连续, 2 表示这段区间的左连续,然后就是一连串的分解判断,详见代码。该题的调试过程多亏了丽丽同学的帮助,自己生成的数据,用别人AC的代码跑结果,然后再和自己的结果比较...
阅读全文
摘要:http://poj.org/problem?id=2533该题是最裸的LIS题,这里有两种方法。代码如下:#include <cstdio>#include <cstring>#include <algorithm>using namespace std;int a[10000], dp[10004];int main(){ int N; while (scanf("%d", &N) == 1) { int ans = 1, m; for (int i = 0; i < N; ++i) { scanf("%d&q
阅读全文
摘要:http://acm.hdu.edu.cn/showproblem.php?pid=3016这题是一个游戏题,名曰:是男人就下一百层。就是给定一系列的坐标,首先是纵坐标,然后是线段的左右坐标,最后是在该条线段的增加或者扣除的血量。解决这题的关键在于如何处理这多条线段的关系,如果是从上而下的话,那么我们能够更新一条边的两个端点下的最优值,那么对于后面加入的边就有下面的动态方程: sum[f] = max( sum(x), f.x1 <= x <= f.x2 ) + val(f) 需要在该边的区域内寻找最大值来更新这条边的两个端点值,这样做显然处理起来较麻烦,时间开销也比较大。所以我们
阅读全文
摘要:Ackerman函数 Ackerman函数定义如下:A(1, 0) = 2A(0, m) = 1 m >= 0A(n, 0) = n + 2 n >= 2A(n, m) = A(A(n-1, m), m-1) n, m >= 1Ackerman函数的反函数 ackerman函数的反函数——α(x)增长极为缓慢。对于可以想象到的n,α(n)都是在5之内的用途 并查集的“路径压缩”算法:在集合的查找过程中顺便将树的深度降低。采用路径压缩后,每一次查询所用的时间复杂度为增长极为缓慢的ackerman函数的反函数——α(x)。对于可以想象到的n,α(n)都是在5之内的。
阅读全文