随笔分类 - ACM
摘要:最小表示法: 初始时,i=0,j=1,分别以i,j,为起始点顺着i,j,往下比较直到找的str[i+k]!=str[j+k],然后分两种情况考虑:1、 str[i+k]>str[j+k],i变成i=i+k+1,j不变,然后继续往下比较。2、 str[i+k]<str[j+k],j变成j=j+k+1,i不变,然后继续往下比较。直到i或j大于串长,找较小者。说说我的疑惑吧: 用枚举方法我们很好理解,一某一点i为起点,不断查看以i后的点为起点的串是否小于以i为起点的串,这理解起来不难。我们假设以i点为起点的串为S1,以j点为起点的串S2,而用最小表示法的话,需要找的S1、S2第一个不相等
阅读全文
摘要:Dilworth定理及其对偶定理的应用,定理的讲解请看如下博客http://blog.csdn.net/xiaohuan1991/article/details/6956629#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;#define MAX 123456789struct node{ int x,y;};node vert[20001];int res[20001];int cmp(node a,node b)
阅读全文
摘要:Stringsobits Time Limit: 1000ms, Special Time Limit:2500ms, Memory Limit:32768KB Total submit users: 40, Accepted users: 22 Problem 10490 : No special judgementProblem descriptionConsider an ordered set S of strings of N (1 <= N <= 31) bits. Bits, of course, are either 0 or 1.This set of strin
阅读全文
摘要:拿五张牌做例子吧,根据题意刻画出如下图形(‘*’代表未知牌)* 1 (1前面有1张未知牌)* * 2 ( 2前面有2张未知牌)* * * 3 (3前面有3张未知牌)* * * * 4 (4前面有4张未知牌)* * * * * 5 (5前面有5张未知牌)我们把它写成一个序列:* 1 * * 2 * * * 3 * * * * 4 * * * * * * 5我们找前5个作为放牌的5个位置,显然1和2的位置确定。* 1 * * 2 把后面的序列中的前3个* * *填充到前面的3个未知牌 :* 1 * * 2接着把后面的3个3 * * 填充到前面的三个未知牌,这时3被确定3 1 * * 2接着把后面的
阅读全文
摘要:这是一个吧A进制数转换为B进制数的问题,如果不用库函数的话,思路清晰但实现起来便有些繁琐了。又因为只有7位数便可以尽情的使用库函数中的strtol和itoa了。strtol的原型为long strtol(const char* s,char ** endp,int base) 含义是:将base进制的字符串s转换为十进制的函数。endp通常为零,它是处理二进制、十六进制的时候必不可少的函数。itoa的原型为 char*itoa(int n,char* s,int base) 含义是:把数值n转换为base进制的函数,存进s中。#include<stdio.h>#include<
阅读全文
摘要:大致题意:求s到t的可行路径上最小值的最大值(有点拗口啊)也就是说从s到t的每一条可行路径上都有一条最小值,有多条路径的话就求这些最小值的最大值。思路:用求最短路的方法来求解,我们可以把flow[]数组用于存储源点到当前点的可行的最大载重量,假如a->b权值为c的话,怎么改松弛条件呢?k=(flow[a]<c) ? flow[a] : c; if(flow[b]<k) flow[b]=k;这就保证了到达某个点的最大载重量。#include<iostream>#include<cstring>#include<queue>using name
阅读全文
摘要:终于尝试了网络流,看了两天的网络流,稍微有点头绪,做了第一道网络流的题感觉还不错。在这过程中让我最苦恼的还是用邻接表的存储结构,现在还是初步了解就不做总结吧。#include<iostream>#include<queue>#include<cstring>using namespace std;#define MAX_INT 1234567890struct node{ int v; int value; int opposite; int next;};node edge[2001];int head[201],pre[201],flow[201],st
阅读全文
摘要:大致题意:给出一个矩阵,矩阵内的值的范围为:[-25,25](注意这个范围),从一个格a走到相邻的格b(a,b代表相应格的值)的速度为2^(a-b)*v,时间就是速度的倒数。问从左上角走到右下角所用的最短时间。很显然是最短路问题,用spfa来求解,该题有一个易出错的地方,因为矩阵内的值范围[-25,25],如果用1<<x的方式求2的幂,很显然这个数会整数超出范围。开始没注意这个问题结果TLE,解决方法可以将1替换为__int64的数。所以dist数组初始化时需将最大值足够大。#include<iostream>#include<cstring>#includ
阅读全文
摘要:大致题意:给出一些点的精确信息和模糊信息,精确信息给出两点的位置和距离,模糊信息给出两点的位置,但距离大于等于一。试确定是否所有的信息满足条件。这道题让我对差分约束系统有了进一步的认识。设dist[i]表示源点到i的距离,精确条件可以判断出两个差分条件:假如a->b为c则可以写成c>=dist[b]-dist[a]>=c;所以可得dist[b]<=dist[a]+c , dist[a]<=dist[b]-c;这就说明a到b有一条长度为c的边,b到a有一条长度为-c的边。模糊信息可以确定一个差分条件由dist[b]-dist[a]>=1可得:dist[a]&l
阅读全文
摘要:大致题意:给出n个闭区间[ai,bi],每个区间对应一个ci,表示集合Z在区间[ai,bi]内ci个相同元素,问集合Z至少有几个元素。思路:将区间[ai,bi]的每个端点看做一个顶点,以dist[i+1]表示源点x到i之间至少有与集合Z相同元素的个数。如果将至少含有的相同元素的个数看做边的权值则一个区间[ai,bi]的两个端点的dist[ai]和dist[bi+1]分别表示源点x到ai-1和bi的距离。那么区间[ai,bi+1]又可以看做什么呢?可以看做ai到bi的一条边。依据题意 x、ai、bi构成了一个边权三角形dist[bi+1]-dist[ai]>=ai->bi,即dist
阅读全文
摘要:大致题意:给出源点和始点,求花费小于coin的条件下的最短路。采用优先队列搜索加cost[i]+cost[i->v]<=coin的进队条件(i->v为i的邻接点)。#include<iostream>#include<queue>#include<cstring>#include<functional>using namespace std;#define MAX_INT 1234567890struct node{ int v; int length; int value; int next;};node edge[10001
阅读全文
摘要:题意也就是求源点到其他个点的最短距离和其他点到源点的最短距离和;源点到其他点的最短距离可在原图中用psfa求出,其他点到源点最短距离可在逆图中用spfa求出。#include<iostream>#include<cstdio>#include<cstring>#include<queue>using namespace std;#define MAX_INT 1234567890struct node{ int v; int value; int next;};node edge1[1000001],edge2[1000001];int head
阅读全文
摘要:题意上有一点要注意:在任何一条路径上,任何两点的等级之差都必须在限制之内。比如说:a、b、c的等级分别为3、2、1,限制为1的话。能和a、b交易就不能和c交易了,因为a和c超出限制。同样,b、c能交易就不能和a交易了,因为a、c任然超出限制。根据题意将每种物品看成每个顶点,优惠价格看成边,便构成一有向图,然后可以用Dijkstra求解。因为有等级限制,求一次Dijkstra是不行的。我看了网上大牛的思想:枚举0~L的每一种限制i,除去不在区间[rand[1]-i,rand[i]+m-i](rand[1]为酋长的等级)的顶点,然后Dijkstra,取其中最小的。#include<iostr
阅读全文
摘要:题意:在一个无向图中,若其最小生成树唯一,则输出其值;若不唯一则输出“Not Unique!”。《算法:C语言实现》这本书将MST有两个重要性质:割性质和环性质。本题则用到了MST的环性质。也就是说在一个无向连通图中可以将边分为MST上的边和非MST上的边,若将非MST上的边e加入MST中一定会形成一个环。所以先用Kruskal算法求出MST,然后以e的一个端点开始在MST上进行深搜,找到到达另一个端点路径,查看这条路径上边的权值是否有和e的权值相等的。若有则不是唯一的,若将每个e都测试一遍都没有和e的权值相等的则是唯一的。这样说够通俗易懂了吧……然而我看到网上很多人用次小生成树的解法来做,这
阅读全文
摘要:题意大致是这样的:在一个有向图里面,在同一个强连通分量里面的点之间的消费为0,不在同一个强连通分量的点之间是有消费的,问从一个点到另一个点的最小消费。很显然在同一个强连通分量的点可以缩为一个点,然后重新构图结果肯定是一棵树。从始点到终点的最小消费可以用记忆化搜索来求解。代码如下:#include<iostream>#include<cstring>#include<stack>using namespace std;#define MAX_INT 1234567890struct node{ int v; int value; int next;};stac
阅读全文
摘要:题意就不说了,很明显的拓扑排序。借这道题总结一下拓扑排序吧。拓扑排序的思路很明确但我总觉得有很多的细节值得注意,写的时候总是缺点这少点那的,不断的调试总是浪费很多的时间,以下是我总结的几点:(1)拓扑排序的结果一般分为三种情况:1、可以判断2、有环出现了矛盾3、条件不足,不能判断,思路上一定要分清楚三种情况的条件判断。(2)初始化栈的时候,将入度为零的顶点入栈,然后弹出栈顶元素e,将e的邻接点的入度减一,若邻接点的入度也为零了,将该邻接点也入栈,如此循环,直到栈空。在这个过程中,栈中元素个数始终为一。若大于一则出现了多个顶点入度为零的情况,这时就无法辨别这几个顶点的先后顺序,这也就是条件不足的
阅读全文
摘要:题目大意:网络中的一学校可以将软件发送给其他一些学校,能够发送给谁取决于他们各自维护的一个清单。将学校看成一个节点,给出每个学校的维护清单,问至少需要复制几次软件,使毎个学校都能够得到该软件,在清单中至少添加几项,可使软件至少复制一次,所有学校都可以得到。思路: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)判断有没有欧拉路径。作为有向图,有欧拉路径的从分条件是:在连通的前提下,始点的出度比入度大一且终点的入度比出度大一且其他的顶点出度等于入度,或者所有顶点出度等于入度。(
阅读全文