07 2011 档案
摘要:题目大意:网络中的一学校可以将软件发送给其他一些学校,能够发送给谁取决于他们各自维护的一个清单。将学校看成一个节点,给出每个学校的维护清单,问至少需要复制几次软件,使毎个学校都能够得到该软件,在清单中至少添加几项,可使软件至少复制一次,所有学校都可以得到。思路:1、用Tarjan算法求出强连通分分量。2、缩点重新构图。3、分别求节点的出度和入度。第一个问题就是出度的个数,第二问题就是出度和入度中的较大者。代码如下:#include<iostream>#include<cstring>#include<vector>#include<stack>u
阅读全文
摘要:本题求关节点的算法与求桥的算法基本相似,只不过在其中加了一个常量时间的测试,那么说一下关节点的判断条件:有两个双连通分量A和B,通过关节点x相连,那么分别处于两个双连通分量的a和b顶点,连接他们的任何路径都必须通过x,那么单考虑B,以x为根B形成的搜索子树中的任何顶点的孩子都不会越过x顶点,也就是说pre[x]<=low[b](pre[],low[]下有说明)总会成立。这道题需要注意的就是找的每一个关节点确定其双连通分量时,因为自身所在部分也是一个双连通分量所以输出时要加一。还有一点就是搜索树的根有两棵或两棵以上的子树时才是一个关节点,所以在确定其连通分量时要减一。代码如下:#inclu
阅读全文
摘要:题大意:给出n个点,编号1~n,给出至少n-1条边。问在需要增加几条边是该图成为双连通图。因为至少有n-1条边,所以一定是连通图,利用tarjan算法找出双连通分量,如果我们把每个双连通分量看成一个顶点,那么就构成了一棵树,再求出叶子的个数m,(m+1)/2就是答案了。我不解的是这道题需要除去重边才能AC........代码如下:#include<iostream>#include<vector>#include<cstring>using namespace std;vector <int> map[5001];int pre[5001],lo
阅读全文
摘要:题意:给你一些单词,能否将这些单词首尾连接起来,即前一个单词的最后一个字母和后一个单词的第一个字母相同,若能输出该序列,若有多种则按字典序输出该序列。如果将每一个单词的首字母和尾字母看成节点,每个单词看成一个线段的话,若满足上述条件,就会构成一个欧拉图,然后就找出符合条件的欧拉路径。(1)构图。以为要按字典序输出,所以单词输入完毕后,进行一趟排序,有大到小排,若采用头插法,邻接表建立后,后面的节点就会自然就会按字典序排好。(2)判断有没有欧拉路径。作为有向图,有欧拉路径的从分条件是:在连通的前提下,始点的出度比入度大一且终点的入度比出度大一且其他的顶点出度等于入度,或者所有顶点出度等于入度。(
阅读全文
摘要:自己总算真正独立的做了一道题,我的思路是这样的:将每一个区域抽象成一个节点,结果就是每个club成员到某一点的最小距离之和。关键就是构图了,每一块相邻的区域,就是直连的两节点,也就是说原图中的每一条边有且仅关联两个区域。在构造图的过程中需要保留club的每个成员可以出发的区域。重新构造图之后对每个顶点进行一次广搜找出最小值就行了。代码如下:#include<iostream>#include<queue>#include<vector>#include<cstring>using namespace std;#define MAX_INT 123
阅读全文
摘要:大致题意:将一条海岸线看成X轴,X轴上面是大海,海上有若干岛屿,给出雷达的覆盖半径和岛屿的位置,要求在海岸线上建雷达,在雷达能够覆盖全部岛屿情况下,求雷达的最少使用量。本题一看就用贪心做,怎么贪呢?先研究一下每个岛屿,设岛屿到海岸线的垂直距离为d,雷达的覆盖半径为k,若d>k,直接输出-1,若d<=k,则雷达的建造有一个活动区间[x1,x2](用平面几何可以求得出来)。因此,在可以覆盖的情况下每个岛屿都有一个相应的活动区间。该问题也就转变成了最少区间选择问题即:在n个区间中选择一个区间集合,集合中的各个区间都不相交,集合中元素的个数就是答案了。代码如下:#include<io
阅读全文
摘要:题意大致是:在一个序列里面,每个元素都是个数字序列,若该数字序列序号为j,则该序列就是1234.....j;输出这个总序列的第i个数字。先把前八十个字符写出来:11212312341234512345612345671234567812345678912345678910123456789101112345678910可以看出每个元素序列所具有的数字个数为该元素序列的位序加一。我的思路是这样的:先找出的i个数字所在的元素序列N,然后再找出第i个数字在第N个元素序列的第M个数字里,然后再求出是M里的那个字符个数字。代码如下:#include<stdio.h>#include<m
阅读全文
摘要:题意:在几个区间里面,挑选出几个数字组成一个集合,使得每个区间都至少有两个数字在这个集合里面,求这个集合的最少数字个数。用贪心来做,开始我是按照每个区间的左端点进行排序,感觉需要考虑多种情况,弄了很长时间没弄出来。然后我有换一种方法来做:按每个区间的右端点从小到大排序,对于每个区间,先查看该区间内有没有数字被选过,若选过则选了几个。若没有被选过则应该选该区间的最后两个数字,若选了一个则选该区间的最后一个数字。具体代码如下:#include<iostream>using namespace std;struct node{ int x; int y;}a[10001];int ss[
阅读全文
摘要:其实也就是求打完boss之前的所有character剩下PH的最大值,在和boss比较,若大于boss则赢,否则则输。打boss之前的所有角色的顺序不同,剩余的PH则不同。所以将前面的n-1个角色全排列就有2^(n-1)种可能。这几乎是不可能求出来的。每个角色在打的过程之中有两种可能打和不打,打用1表示,不打用0表示,那么20个数就可以用20位来表示,所以0~2^(n-1)每个数都表示一个状态,每个数之间都可以互相转化。假设dp[i][j]表示打j状态为i的剩余PH,那么状态转移方程就可以写为:dp[i][j]=max{dp[i][j],dp[i-j][k]+a[j][1]-a[j][0]};
阅读全文
摘要:题大意是:给你一棵节点为n的树,问至少砍几刀可以孤立出一棵节点为m的子树。设d[i][j]为以i为根节点孤立出节点为j的子树至少需要砍得次数(注意:这个子树是包括根节点i的)。接下来再说说怎么得到状态转移方程:(1)当j为1的话,d[i][1]=节点i孩子的个数;(2)若以i的孩子son[i]为根的子树不在以i为根节点孤立出节点数为j的子树的内部,则有没有以son[i]为根的子树无所谓;若以son[i]为根节点的子树有k个节点在以i为根孤立出节点数为j的子树中则整个树分成两部分,此时,d[i][j]=d[i][j-k]+d[son[i]][k]-1;之所以减一是因为两个分开的子树重组在一起需要
阅读全文