摘要:
两个星期的“图论”练习结束了,原来自己只会一个Dijstra()算法,现在又学到了bellman()、Floyd()、最小生成树prime()算法以及拓扑排序topqsort()、最小路最大流(其实我都看不懂)算法。一开始的时候,因为是英文题,理解题目有些难度,花费了一定量的时间。其实,有些题只要能够完全理解透题意,那么在写程序的时候需要注意的地方基本上就清楚了。所以,读透题是关键,有时候虽然精通算法,但是马马虎虎读题,照样不能AC,我曾经经历过这样的事情,因此对这个教训记忆也比较深刻。上述几个算法,各自有自己的用途:Dijstra()主要用于求单源最短路径;bellman()用于处理环和负权 阅读全文
摘要:
拓扑排序方法如下: (1)从有向图中选择一个没有前驱(即入度为0)的顶点并且输出它. (2)从网中删去该顶点,并且删去从该顶点发出的全部有向边. (3)重复上述两步,直到剩余的网中不再存在没有前驱的顶点为止.这个题是标准的拓扑排序,但需注意这句话:where xxx is the number of relations processed at the time either a sorted sequence is determined or an inconsistency is found, whichever comes first, 也就是说一旦可以确定顺序或者出现环,就要立即输出鄙 阅读全文
摘要:
最小生成树,只不过要求的是树中的最大权值。源程序:#include<stdio.h>#define max 0xfffffff#define N 505int s[N],map[N][N],dist[N],n;int prime(){int min,a,u,i,j;for(i=1;i<=n;i++){s[i]=0;dist[i]=map[1][i];}s[1]=1;u=1;min=0;for(i=1;i<n;i++){a=max;for(j=1;j<=n;j++)if(s[j]==0&&dist[j]<a){a=dist[j];u=j;}if 阅读全文
摘要:
很典型的最小生成树,不说什么了。源代码:#include<stdio.h>#define max 0xfffffff#define N 105int map[N][N],dist[N],s[N],n;int prime(){int i,j,u,a,sum;for(i=1;i<=n;i++){s[i]=0;dist[i]=map[1][i];}s[1]=1;u=1;sum=0;for(i=1;i<n;i++){a=max;for(j=1;j<=n;j++)if(s[j]==0&&dist[j]<a){a=dist[j];u=j;}s[u]=1; 阅读全文
摘要:
一开始的时候没看懂题意,看来,英语有待提高。大意是:两个字符串之间的距离定义为不同字母的个数,而除了第一个串,任一串可以由其他的字符串转换过来,要求的就是最短的距离和。用到的算法就是最小生成树prime()算法源代码:#include<stdio.h>#define max 0xfffffff#define N 2005int s[N],dist[N],distance[N][N],n;char map[N][10];int prime(){int i,j,u,a,sum;for(i=1;i<=n;i++){s[i]=0;dist[i]=distance[1][i];}s[1 阅读全文
摘要:
Floyd算法简介:连接任何两个点i和j,假设通过第三个点k,如果a[i][j]>a[i][k]+a[k][j],则a[i][j]=a[i][k]+a[k][j];也就是说,如果原来i和j之间的距离大于i到k与k到j距离之和,那么i和j之间的最短距离就要发生改变。这个题理解起来有点难度,其实是要求出由某个人向其他所有人发短信所用的最短时间,而一个人完成这项工作最快用时是由他人发短信花费最长时间决定的。于是,可以先用Floyd算法求出从i到j的最短联通时间a[i][j],然后对应每一个i,求出到j的最长联通时间,最后从这些时间中求出答案。可能听起来不太懂,具体看程序吧。Floyd第一道!! 阅读全文
摘要:
这是道中文题,意思应该好理解。如果可以用物品n代替物品m,那么节点n和m是连接的,这样就可以转化成图的问题,然后求最短路径。用到的算法是Dijstra(),但是在处理等级和dist[]的时候比较麻烦。一开始我是把1作为开始点,然后去查找,wrong了好久。后来,到网上看大牛的博客,发现一个好方法:从其他各点开始一直找到1节点,因为只有拿到酋长的允诺才能娶到酋长的女儿。另外,等级问题可以用枚举法,假设节点1的等级是5,m的取值是3,那么只有在等级是2~5,3~6,4~7,5~8这几种情况中选择节点。只有思路清楚、正确,代码才容易写正确。源代码:#include<stdio.h>#de 阅读全文
摘要:
这是一个用bellman()判断有无负权环的题目,需要先对图中的每一个元素进行操作,最后判断负环是否存在。要注意有向图的边权是负数。具体见源程序:(PS:本题也可以用spfa来做,就是通过队列中元素的进出掌握每个节点的情况)#include<stdio.h>typedef struct{int a,b,t;}node;node road[6000];int n,m,w,s,e,t,ep;int bellman(){int dist[502],i,j,temp; for(i=1;i<=n;i++)dist[i]=0;for(i=1;i<n;i++){temp=0;for( 阅读全文
摘要:
题目的大意是:有n种货币和m种转换方式,每种转换方式对应的汇率r和手续费c,假设原来的钱数是v,那么转换后的为(v-c)*r。现在给某种货币形式的钱数,问能否经过某些转换方式使得变回同种货币形式时钱数增加。用到的算法是bellman()的最大路的松弛法。需要注意:1.满足正环条件就要不停松弛,直到dist[s]>value;2.如果不能循环了就要return dist[s]>value;源程序:#include<stdio.h>#include<string.h>typedef struct{int u,v;double r,c;}node;node edg 阅读全文
摘要:
不知不觉,五天已经过去了,“搜索”专题也要接近尾声了,因为以前接触过“搜索”,一开始总感觉“深搜”和“广搜”挺容易的,尤其是广搜,照着”模板“直接写代码,屡试不爽。后来,经过不断地做题,我才发现,以前我所了解的搜索,只是冰山一角,”搜索“复杂着呢。无论&r... 阅读全文