图论学习

最短路径

算法之间的区别

迪杰克斯拉算法

int dijkstra(int k)
{
	dis[1]=0;
	for(int m=2;m<=k;m++)
		dis[m]=1e9;//初始化dis数组
	vis[1]=1;
	for(int n=1;n<=k;n++)
	{
		for(int m=1;m<=k;m++)
		{
			int minpath=1e9;
			if(!vis[m]&&dis[m]<minpath)
			{
				minpath=dis[m];
				int mark=m;
			}
		}
		vis[mark]=1;
		for(int m=1;m<=k;m++)
		{
			if(!vis[m]&&dis[n]>dis[m]+[m][mark])
				dis[n]=dis[m]+[m][mark];
		}
	}
}		

Floyd算法

for(k=1;k<=n;k++)  
	for(i=1;i<=n;i++)  
		for(j=1;j<=n;j++)  
			if(e[i][j]>e[i][k]+e[k][j] )   
				e[i][j]=e[i][k]+e[k][j];  

Spfa

ford的队列实现,已死。

Bellman-ford

求最短路径

forint m=0;m<city;m++)
	for(int n=0;n<edge;n++)
		path[m]=min(path[n]+map[n][m],path[m])

求有无环

for(i=1;i<=enum;i++) //检查有无负权环  
{  
     if(d[edge[i].v]>dis[e[i].u]+edge[i].w)  
     {  
          flag = false;//存在负环  
          break;  
     }  
} 

最小生成树

prim算法

Kruskal算法

不形成环的前提下,按照边权重从小到大排序

struct node{
	int x,y;
	int weight;
}n[5000];
int parent[k];
int fatherfind(int k)
{
	if(parent[k]==k)
		return parent[k];
	else
		parent[k]=fatherfind(parent[k]);
}
int cmp(node a,node b)
{
	return a.weight<b.weight;
}
sort(n,n+5000,cmp);//会按照weight大小从小到大排序
forint m=0;m<n;m++)
{
	int x=n[m].x;
	int y=n[m].y;
	if(fatherfind(x)!=fatherfind(y))
		parent[fatherfind(x)]=y;
}

拓扑排序

基本思路是:从入度或(出度)为0的点出发,一层层向上滚动,滚动一层则剔除该点,直到整个图全被遍历为止

int topo(int k)
{
	for(m=1;m<=k;m++)
	{
		if(!indegree[m])
			q.push(m);
	}
	while(!q.empty())
	{
		int k=q.front();
		q.pop();
		for(int m=1;m<=k;m++)
		{
			if(indegree[m]==0)
				q.push(m);
		}
	}
}

tarjan算法求割点

root节点,判断是否有两棵子树即可
非root节点,判断其子树与自身有无连接

int low[u];
int dfn[u];
void tarjan(int u,int from)
{
	dfn[u]=low[u]=++idx;//更新时间戳
	int child=0;
	for(int i=head[u];i!=0;i=e[i].next)
	{
		int nx=e[i].to;
		if(!dfn[nx])//如果未访问过
		{
			tarjan(nx,from)//回溯
			low[u]=min(low[u],low[nx]);//取最早碰到自己的那个
			if(low[nx]>=dfn[u]&&u!=from)//不通过u,无法访问到其,则一定是割点
				cut[u]=true;
			if(u==from)
				child++;
		}
		low[u]=min(low[u],low[nx]);
	}
	if(child>=2&&u==from)//root节点
		cut[u]=true;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值