图论入门(一),拓扑排序生成拓扑序列与Dijkstra求最短路

基本知识

Dijkstra基本思想
拓扑排序思维视频讲解

848:有向图的拓扑排序

题目链接
题解:

#include<bits/stdc++.h>
using namespace std;
const int N=100010;
int n,m;
int h[N],e[N],ne[N],idx;
int d[N];//d[j]代表点j的入度数量 
int q[N];//用数组模拟队列,避免queue中的pop,保留元素 
void add(int a,int b)//建立邻接表存储图 
{
	e[idx]=b;
	ne[idx]=h[a];
	h[a]=idx++;
}
bool topsort()//模拟队列,判断是否为有向无环图 
{
	int hh=0,tt=-1;//队头,队尾 
	for(int i=1;i<=n;i++)
	{
		if(!d[i]) q[ ++tt ] = i ;//将入度为0的点入队 
	}
	while(tt>=hh)
	{
		int t=q[hh++];
		for(int i=h[t];i!=-1;i=ne[i])
		{
			int j=e[i];
			if(--d[j]==0)
			{
				q[++tt]=j;
			}
		}
	}
	return tt==n-1;
	//表示n个点都入队了,则为有向无环图,即拓扑图 
}
int main()
{
	cin>>n>>m;
	memset(h,-1,sizeof h);
	for(int i=0;i<m;i++)
	{
		int a,b;
		cin>>a>>b;
		add(a,b);
		d[b]++;
	}
	if(topsort())
	{
		for(int i=0;i<n;i++) cout<<q[i]<<" ";
	}
	else
	{
		cout<<-1;
	}
	return 0;
}

849:Dijkstra求最短路I – 朴素实现

题目
题解:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=510;
int dis[N],pic[N][N];
bool st[N];//标记该点的最短距离是否已经被确定 
//未优化版本 
int main()
{
	int n,m;
	cin>>n>>m;
	memset(pic,0x3f,sizeof(pic));
	for(int i=1;i<=m;i++)
	{
		int u,v,w;
		cin>>u>>v>>w;
		pic[u][v]=min(pic[u][v],w);//对于重边的处理 
	}
	memset(dis,0x3f,sizeof(dis));
	dis[1]=0;//到自身距离为0 
	for(int i=1;i<=n;i++)//有n个点所以n次迭代 
	{
		int t=-1;//t用于储存当前被访问的点 
		for(int j=1;j<=n;j++)
		{
			//改不走寻找还未确定的最短路的点当中 路径最短的点 
			if(!st[j]&&(t==-1||dis[t]>dis[j]))
				t=j;
		}
		st[t]=1;//到t点的最短路已经确定 
		for(int j=1;j<=n;j++)//依次更新每个点到相邻的点的最短路<--新确定的最短路的点会影响未确定的点 
			dis[j]=min(dis[j],dis[t]+pic[t][j]);
	}
	if(dis[n]==0x3f3f3f3f) cout<<-1<<endl;//到n点没有路径 
	else cout<<dis[n];
	return 0;
}

850. Dijkstra求最短路 II – 优化

题目
题解:面对数据较大情况(点的数量超过1e5,不再适合用二维数组存,二维数组开到1e5会爆),使用优先队列优化,使用临界矩阵存图(适用于稀疏图)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e6+10;
typedef pair<int, int> pii;
int dis[N];
int h[N],e[N],ne[N],idx;
int w[N];//存权重 
bool st[N];//标记该点的最短距离是否已经被确定
//优化版本,用邻接矩阵存图 
void add(int a,int b,int c)
{
	e[idx]=b;
	w[idx]=c;
	ne[idx]=h[a];
	h[a]=idx++;
}
int main()
{
	int n,m;
	cin>>n>>m;
	memset(h,-1,sizeof(h));
	for(int i=1;i<=m;i++)
	{
		int u,v,w;
		cin>>u>>v>>w;
		add(u,v,w); 
	}
	
	memset(dis,0x3f,sizeof(dis));
	dis[1]=0;//到自身距离为0 
	priority_queue<pii, vector<pii>, greater<pii> >heap;
	heap.push({0,1});//先存距离,再存点
	while(heap.size())
	{
		auto t=heap.top();
		heap.pop();
		int ver=t.second,distance= t.first;
		if(st[ver]) continue;
		st[ver]=true;
		for(int i=h[ver];i!=-1;i=ne[i])
		{
			int j=e[i];
			if(dis[j]>dis[ver]+w[i])
			{
				dis[j]=dis[ver]+w[i];
				heap.push({dis[j],j});
			}
		}
	}
	if(dis[n]==0x3f3f3f3f) cout<<-1<<endl;//到n点没有路径 
	else cout<<dis[n];
	return 0;
}

P4779 【模板】单源最短路径(标准版)

题目
上述Dijkstra都是寻找从1到n的最短路,本题寻找从第s个点出发,到每个点的距离
题解:

#include<bits/stdc++.h>
#define pii pair<int, int>
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const int N=1e5+10;
int n,m,s;
ll dis[N];
bool vis[N];
struct node
{
	int to,len;
};
vector<node> f[N];
void diji(int t)
{
	memset(dis,inf,sizeof(dis));
	memset(vis,0,sizeof(vis));
	dis[t]=0;//注意初始化
	priority_queue<pii, vector<pii>, greater<pii> >q;
	q.push(pii(0,t));//从第t个点开始的精髓于此
	while(!q.empty()){
		pii p=q.top();
		q.pop();
		int tt=p.second;
		if(vis[tt]) continue;
		vis[tt]=true;
		for (int i=0;i<f[tt].size();i++)
		{
			node a=f[tt][i];
			if(dis[a.to]>dis[tt]+a.len)
			{
				dis[a.to]=dis[tt]+a.len;
				q.push(pii(dis[a.to],a.to));
			}
		}
	}
}
int main()
{
	cin>>n>>m>>s;
	for(int i=1;i<=m;i++)
	{
		int u,v,w;
		cin>>u>>v>>w;
		f[u].push_back({v,w});
	}
	diji(s);
	for(int i=1;i<=n;i++) cout<<dis[i]<<" ";
}

总结

今天是学习图论第一天…加油,道阻且长…

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值