图算法小结

一:起因

(1)关于图的算法一般是比较复杂的,自己在这方面也是比较弱的,首先是图的存储问题 和 遍历问题:

存储分为两种,邻接矩阵 和 临街表;遍历分为DFS 和 BFS两种,非常类似于二叉树的先跟遍历和层次遍历。

(2)图在实际应用中是非常广泛的,这与万物归一,万物相连的理论是一致的,两个物体之间有着千丝万缕的联系,我们成这种联系建立的网络为图(带权图);联系的强弱为边的权重。

(3)图的一些复杂的算法,也是建立在两种遍历图的思想的基础上进行的,所以我们先从简单的谈起。

二:代码示例

(1)最简单的图的遍历问题

Lake Counting

Sample Input

10 12

W........WW.

.WWW.....WWW

....WW...WW.

.........WW.

.........W..

..W......W..

.W.W.....WW.

W.W.W.....W.

.W.W......W.

..W.......W.

Sample Output

3

要求输出图中连通分支的个数,最简单的图遍历问题。

图的常见遍历方式有两种:深度优先遍历和广度优先遍历,他们的作用是将图中的每个点都访问一遍,只不过是顺序不同。

如果把图中的每条边长都相等(比如都是1)的话,深度优先遍历过程就是尽可能深的去访问节点,具体过程为:

1.任意选定一个点p0作为遍历的起点

2.当访问到某一个节点p1时,如果p1下面有未被遍历的子节点,我们就接着访问p1的某一个未被遍历子节点,并标记该子节点被访问过,

3.如果p1不存在未被访问的子节点,我们就退回到p1的父节点,并执行第2步

4.执行第2、3步,直到所有节点被访问过。

大家也看出来了,深度优先遍历的是一个递归的过程,因此很容易想到要用到栈这种数据结构,具体实现的时候可以用递归,也可以用栈。看个人习惯了。

广度优先遍历实现就要用到队列了。以下是poj2386不同实现方式的代码

#include <iostream>
#include <string>

using namespace std;

const int MAX_SIZE = 102;
string strs[MAX_SIZE];
int n,m;
int dir[8][2] = {{-1,0},{-1,-1},{0,-1},{1,-1},{1,0},{1,1},{0,1},{-1,1}};
inline bool isBound(int x,int y)
{
    return (x<0 || x>=m || y<0 || y>=n);
}
void dfs(int xindex,int yindex)
{
    strs[xindex][yindex] = '.';
    int i,x,y;
    for(i=0; i<8; ++i)
    {
        x = xindex+dir[i][0];
        y = yindex+dir[i][1];
        if(!isBound(x,y) && strs[x][y]=='W')
        {
           dfs(x,y);
        }
    }

}

int main()
{
    int i,j;
    cin >> m >> n;
    getline(cin,strs[0]);//¿ÕÐйýÂË
    for(i=0; i<m; ++i)
    {
        getline(cin,strs[i]);
        //cout << strs[i] << " i= " << i << endl;
    }
    int ans = 0;
    for(i=0; i<m; ++i)
    {
        for(j=0; j<n; ++j)
        {
            if(strs[i][j]=='W')
            {
                //cout << strs[i][j];
                ans ++;
                dfs(i,j);
            }
        }
    }
    cout << ans << endl;
    cin >> n;
    return 0;
}

(2)最小生成树

题意:北极有一些村庄,现需要在这些村庄间建立起通讯,有s个卫星频道,任何两个拥有卫星频道的村庄都可以直接通过卫星进行通讯而无视距离,没有卫星的村庄通过无线电进行通讯,并且这两个村庄的距离不能超过D,D值取决于无线电收发器的功率,功率越大,D值越大,但价格也越高,出于购买费用和维护费用的考虑,所有村庄的无线电收发器都相同,即D值相同,现要求在保证任意两个村庄间都能直接或间接通讯,并且D值最小,输出这个最小值。就是输出最小生成树最大边的权值,但是卫星频道是不确定因素。这道题有个很好的解法及证明。

其实题目意思是将一棵最小生成树转化成一个森林,森林里有S棵树,每棵树配一个卫星频道,并且使得森林里所有边中最长的边的长度最小

其实意思就是可以删除最小生成树中的S-1条边,问剩下的边中最长的是多少

由于建图时每两个点之间都有边,是稠密图,故用Prim法比较好 ---- 有的题目也稍微复杂一点,首先得判断是否联通,再求最小生成树

#include <iostream>
#include<cmath>
#include<algorithm>

using namespace std;

const int INF = 1000000;
const int MAX_SIZE = 501;
double map[MAX_SIZE][MAX_SIZE];
double path[MAX_SIZE];

struct node
{
    int x;
	int y;
}point[MAX_SIZE];
//记录从顶点集U到V-U的代价最小的边的辅助数组定义
struct
{
    int adjvex;
    double lowcost;
}closedge[MAX_SIZE];
bool cmp(double a,double b)//从大到小偏序
{
    return a>b;
}
// 求距离
inline double CalDist(struct node  &a, struct node &b)
{
	double xx = (a.x-b.x);
	double yy = (a.y-b.y);
	return sqrt(xx*xx + yy*yy);
}
//用普里姆算法从第k个顶点出发构造网G的最小生产树T,N个顶点的图
void prim(int k,int n)
{
	int i,j;
    for(j=1;j<=n;j++)//辅助数组初始化
	{
        if(j!=k)
        {
            closedge[j].adjvex=k;
            closedge[j].lowcost=map[k][j];
        }
	}
	closedge[k].lowcost=0; //初始,U={u},这里将0作为访问过的标志
	int l=0;
	for(i=1;i<n;i++)//选择其余n-1个顶点,这个i不无任何实际意义,仅仅是选取n-1个点,记录次数而已
	{
		double min=INF;
		for(j=1;j<=n;j++)//求出T的下一个结点:第k顶点,最小的,不成环(即未访问过)
		{
			if(closedge[j].lowcost!=0&&min>closedge[j].lowcost)
			{
				k=j;
				min=closedge[j].lowcost;
			}
		}
		closedge[k].lowcost=0; //第k顶点并入U集
		path[l++]=map[k][closedge[k].adjvex]; //保存该边,要是求最小生成树的成本,就得改成加和了,要是求最小生成树的最大边权值,就得比较最大值了
		for(j=1;j<=n;j++) //新顶点并入U后重新选择最小边
		{
			if(map[k][j]<closedge[j].lowcost)
			{
				closedge[j].adjvex=k;
				closedge[j].lowcost=map[k][j];
			}
		}// end of for
	}// end of for
}

int main()
{
    int t,m,n;
	int i,j;
    cin>>t;
    while(t--)
    {
        cin>>m>>n;
		// input
        for(i=1;i<=n;i++)
        {
			cin>>point[i].x>>point[i].y;
		}
		// init dist
        for(i=1;i<=n;i++) //求出毎两个顶点之间的距离
		{
            for(j=1;j<i;j++)
			{
                map[i][j]=map[j][i]=CalDist(point[i],point[j]);
				//cout << map[i][j] << endl;
			}
		}
		for(i=1;i<=n;i++)
		{
			map[i][i]=INF;
		}
		// prime
		prim(1,n);
		sort(path,path+n-1,cmp); //把构成最小生成树的n-1条边从大到小排序
		cout.setf(ios::fixed);//保留两位小数
		cout.precision(2);
		cout<<path[m-1]<<endl;//数组d从下标0开始存储,即第m条边
    }
    return 0;
}

(3)

时间: 2024-11-13 06:38:45

图算法小结的相关文章

图算法小结(prime与dijkstra对比)

(0)Dijstra 最短路径和prim最小生成树算法,神似,只是在更新dist时的if条件不同:主要是这种prime 的计算两个集合间的最小值的思想非常重要. (1)某省自从实行了很多年的畅通工程计划后,终于修建了很多路.不过路多了也不好,每次要从一个城镇到另一个城镇时,都有许多种道路方案可以选择,而某些方案要比另一些方案行走的距离要短很多.这让行人很困扰. 现在,已知起点和终点,请你计算出要从起点到终点,最短需要行走多少距离. Input 本题目包含多组数据,请处理到文件结束. 每组数据第一

18大经典数据挖掘算法小结

18大经典数据挖掘算法小结 本文所有涉及到的数据挖掘代码的都放在了我的github上了. 地址链接: https://github.com/linyiqun/DataMiningAlgorithm 大概花了将近2个月的时间,自己把18大数据挖掘的经典算法进行了学习并且进行了代码实现,涉及到了决策分类,聚类,链接挖掘,关联挖掘,模式挖掘等等方面.也算是对数据挖掘领域的小小入门了吧.下面就做个小小的总结,后面都是我自己相应算法的博文链接,希望能够帮助大家学习. 1.C4.5算法.C4.5算法与ID3

[blog]基于卷积神经网络的以图搜图算法实现

基于卷积神经网络的以图搜图算法实现        如果用这个名称去搜索论文,一定有不少.为什么了,因为从原理上来看,卷积神经网络就非常适合找图片的相似的地方.想想看,许多大牛.小牛.微牛的文章都是说如何从mnist中.从CIFA10中.从CIFA100中去找到相似的图片.那么,反过来想一想,如果那么复杂的数据卷积神经网络都能够去处理,那么对于这种相对来说,比较简单的"以图搜图"的需求,应该更容易来解决.这里的神经网络解决这个问题,还是尝试得到一种较为通用的问题解决方法. 零.数据集的创

使用Apache POI导出Excel小结--导出XLS格式文档

使用Apache POI导出Excel小结 关于使用Apache POI导出Excel我大概会分三篇文章去写 使用Apache POI导出Excel小结--导出XLS格式文档 使用Apache POI导出Excel小结--导出XLSX格式文档 使用Apache POI导出Excel--大数量导出 导出XLS格式文档 做企业应用项目难免会有数据导出到Excel的需求,最近在使用其,并对导出Excel封装成工具类开放出来供大家参考.关于Apache POI Excel基本的概念与操作我在这里就不啰嗦

【转载】小结一下linux 2.6内核的四种IO调度算法

在LINUX 2.6中,有四种关于IO的调度算法,下面综合小结一下: 1) NOOP NOOP算法的全写为No Operation.该算法实现了最最简单的FIFO队列,所有IO请求大致按照先来后到的顺序进行操作.之所以说“大致”,原因是NOOP在FIFO的基础上还做了相邻IO请求的合并,并不是完完全全按照先进先出的规则满足IO请求.NOOP假定I/O请求由驱动程序或者设备做了优化或者重排了顺序(就像一个智能控制器完成的工作那样).在有些SAN环境下,这个选择可能是最好选择.Noop 对于 IO

Android基础入门教程——8.1.3 Android中的13种Drawable小结 Part 3

Android基础入门教程--8.1.3 Android中的13种Drawable小结 Part 3 标签(空格分隔): Android基础入门教程 本节引言: 本节我们来把剩下的四种Drawable也学完,他们分别是: LayerDrawable,TransitionDrawable,LevelListDrawable和StateListDrawable, 依旧贴下13种Drawable的导图: 1.LayerDrawable 层图形对象,包含一个Drawable数组,然后按照数组对应的顺序来

Android基础入门教程——8.1.2 Android中的13种Drawable小结 Part 2

Android基础入门教程--8.1.2 Android中的13种Drawable小结 Part 2 标签(空格分隔): Android基础入门教程 本节引言: 本节我们继续来学习Android中的Drawable资源,上一节我们学习了: ColorDrawable:NinePatchDrawable: ShapeDrawable:GradientDrawable!这四个Drawable~ 而本节我们继续来学习接下来的五个Drawable,他们分别是: BitmapDrawable:Insert

安卓小结《1》

Activity的生命周期和启动模式的知识点小结: 1.如果Activity切换的时候,新Activity是透明,旧的不会走onStop方法. 2.新的Activity切换的时候,旧Activity  会先执行,onpause,然后才会启动新的activity. 3. Activity在异常情况下被回收时,onSaveInstanceState方法会被回调,回调时机是在onStop之前,当Activity被重新创建的时 候,onRestoreInstanceState方法会被回调,时序在onSt

date命令小结

在写linux shell脚本时,date是经常要用到的一个命令,这篇文章就此做个小结,以防自己用到时到处找 1.最基本的,显示当前的具体时期:直接敲入 date即可,如下, [email protected]:~/scripts$ date 2015年 01月 03日 星期六 21:46:49 CST 2.显示某个文件上次修改的时间:date -r file [email protected]:~/scripts$ date -r save.sh 2015年 01月 02日 星期五 23:29