【思维导图】
【学习总结】
- 深度遍历算法、广度遍历算法:容易理解,便于找寻,比较基础
- 拓扑排序算法:并不一定唯一,要有向图以及判断有没有环路
-
- Prim和Kruscal算法:都是从连通图中找出最小生成树的算法。Prim算法直接查找,多次寻找邻边的权重最小值,而Kruskal是需要先对权重排序后查找的,则Kruskal算法效率比Prim快。
- Dijkstra算法:使用了广度优先搜索解决赋权有向图最短路径问题,以起始点为中心向外层层扩展,直到扩展到终点为止,最终得到一个最短路径
【设计思路】直接用图的遍历,遍历的时候判断是否颜色相等即可。
注意需要不同颜色的个数需要等于k。
【代码截图】
【提交列表】
【测试点】
【错误改正】
先开始在遍历的时候没有在二维数组中的序列搞对,循环时出现错误,遍历不完全;
后来发现还是在数组的循环遍历时出现问题,改正后答案正确;
【提交列表】
【代码截图】
【测试点】
【错误改正】
这个题是从网上找的,网上给的思路是
edge数组的作用记录两点间边的权值,默认的是所有点中 到点v最小的边值几位edge[v]
book数组的作用是记录某点x是否进入了树中,记录了标记为1,没进入的话标记为0;
每当找到一个点,就不断更新edge数组的边值;
错误我自己也没看懂还。
【代码思路】
算法思路:使用并查集
1、把具有朋友关系的人(两个人之间是朋友关系,或、有共同的朋友(只要有共同的朋友且两个人不是朋友,不管这两个人是不是敌人))放在一个集合里面。例如:{a,b,c,d,e},{f,g,h},其中abcde和fgh都不是朋友或者没有共同朋友。具体做法:First:将每一个人作为一个集合
Second:使用WeightedUnion(使用加权规则得到改进的Union操作)把具有朋友关系的人放在同一个集合里。
2、用二维数组bad存储敌对关系。
说明:如果b,c的共同朋友是a,但b,c是敌对关系则abc的集合为{a->{b,c}}(想象一下树中a为根节点,b,c为a的子女节点……)
判断:情况一:a,b在同一个集合中,且bad[a][b]=1
情况二:a,b不在同一个集合中,且bad[a][b]=1
情况三:a,b在同一个集合中,且bad[a][b]=-1
情况四:a,b在不在同一个集合中,且bad[a][b]=-1;
【代码截图】
【提交列表】
【测试点】
【错误改正】
在这种遍历中我经常会发生顺序的错误,便利时数组的序号搞错,到最后遍历时不完全;
网上的代码写的很详细,有自己理解过。
【最后排名】
【阅读代码】
- #include
- #include
- #include
- #include
- using namespace std;
- int n, m, s,q;
- int b[600];
- int a[600][600];
- int c[600];
- int pre[600];
- int inf;
- int sx[600];
- int toval[600];
- int main()
- {
- memset(a, 0, sizeof(0));
- int pathnum[600];
- inf=99999999;
- scanf("%d%d%d%d", &n, &m, &s, &q);
- int i;
- int j;
- for(i=0; i
- for(j=0; j
- {
- if(i==j)a[i][j]=0;
- else a[i][j]=inf;
- }
- for(i=0; i
"%d", &b[i]); - for(i=0; i
- {
- int x, y, z;
- scanf("%d%d%d", &x, &y, &z);
- if(z
- }
- int vis[600];
- for(i=0; i
- {
- vis[i]=0;
- c[i]=inf;
- toval[i]=0;
- }
- int k;
- c[s]=0;
- vis[s]=1;
- pathnum[s]=1;
- toval[s]=b[s];
- {
- for(i=0; i
- {
- int mini, minn;
- mini=s;
- minn=inf;
- for(j=0; j
- {
- if(vis[j]==0 && minn>c[j])
- {
- mini=j;
- minn=c[j];
- }
- }
- vis[mini]=1;
- for(j=0; j
- {
- if(vis[j]==0) if(c[mini]+a[mini][j]
- {
- c[j]=c[mini]+a[mini][j];
- pre[j]=mini;
- toval[j]=b[j]+toval[mini];
- pathnum[j]=pathnum[mini];
- }
- else if(c[mini]+a[mini][j]==c[j] )
- {
- if( toval[j]
- {
- toval[j]=b[j]+toval[mini];
- pre[j]=mini;
- }
- pathnum[j]+=pathnum[mini];
- }
- }
- }
- }
- int top=0;
- j=q;
- while(j!=s)
- {
- sx[top++]=j;
- j=pre[j];
- }
- sx[top]=j;
- printf("%d %d\n", pathnum[q], toval[q]);
- for(; top>=0; top--)
- {
- printf("%d", sx[top]);
- if(top!=0)printf(" ");
- }
- return 0;
- }
【学习总结】
图这一章中最重要的是对数据的遍历,在制作二维或三维数组是对数据的排列,对数据取出的方式路径的选择;
不同的方法有不同的用数据路径,时间复杂度代码效率都不同,在使用时应该比较各个方面后再使用;
学完图这一章之后,理解了许多储存的结构,和对取出数据的方法的认识。