图论 拓扑排序 最短路 的几个模板(Java)

topsort

	static boolean topsort()
	{
	    hh=0;tt=-1;
	    for(int i=1;i<=n;++i)
	    {
	        if(d[i]==0)q[++tt]=i;
	    }
	    while(hh<=tt)
	    {
	        int t=q[hh++];
	        for(int i=h[t];i!=-1;i=ne[i])
	        {
	            int j=e[i];
	            d[j]--;
	            if(d[j]==0)q[++tt]=j;
	        }
	    }
	    if(tt==n-1)return true;
	    return false;
	}

下面四个最短路算法里,只有bell_ford算法不需要st数组,后三个是迭代,判断是否存在最短路需要if(dist[n]>INF/2)来判断 ,spfa判断负环就多了两行,spfa和优先队列dijkstra很像

朴素dijkstra

	static void dijkstra(int u)
	{
	    Arrays.setAll(dist,x->INF);
	    dist[u]=0;
	    for(int i=0;i<n;++i)
	    {
	        int t=-1;
	        for(int j=1;j<=n;++j)
	        {
	            if(st[j]==false&&(t==-1||dist[t]>dist[j]))t=j;
	        }
	        st[t]=true;
	        for(int j=1;j<=n;++j)
	        {
	            if(dist[j]>dist[t]+g[t][j])dist[j]=dist[t]+g[t][j];
	        }
	    }
	}

优先队列dijkstra

	static void dijkstra(int u)
	{
	    Arrays.setAll(dist,x->INF);
	    dist[u]=0;
	    PriorityQueue<pair> q=new PriorityQueue<pair>(new mcomp());
	    q.offer(new pair(u,0));
	    while(!q.isEmpty())
	    {
	        pair t=q.poll();
	        for(int i=h[t.id];i!=-1;i=ne[i])
	        {
	            int j=e[i];
	            if(dist[j]>t.w+w[i])
	            {
	                dist[j]=t.w+w[i];
	                q.offer(new pair(j,dist[j]));
	            }
	        }
	    
c++版本
void dijkstra2(int u)
{
	for(int i=1;i<=n;++i)dist[i]=INF;
	dist[u]=0;
	priority_queue<node> q;
	q.push(node(u,0));
	while(!q.empty())
	{
		node t=q.top();q.top();
		if(st[t.id])continue;
		st[t.id]=true;
		for(int i=h[t.id];i!=-1;i=ne[i])
		{
			int j=e[i];
			if(dist[j]>dist[t.id]+w[i])
			{
				dist[j]=dist[t.id]+w[i];
				q.push(node(j,dist[j]));
			}
		}
	}
}

bell_ford

	static void bell_ford(int u)
	{
		Arrays.setAll(dist, x->INF);
		dist[u]=0;
		for(int i=0;i<k;++i)
		{
			backup=dist.clone();
			for(int j=0;j<m;++j)
			{
				int a,b,w;
				a=es[j].a;
				b=es[j].b;
				w=es[j].w;
				dist[b]=Math.min(dist[b], backup[a]+w);
			}
		}
	}

if(dist[n]>INF/2)

spfa

	static void spfa(int u)
	{
		Arrays.setAll(dist, x->INF);
		q.offer(u);
		dist[u]=0;
		st[u]=true;
		while(!q.isEmpty())
		{
			int t=(int)q.poll();
			st[t]=false;
			for(int i=h[t];i!=-1;i=ne[i])
			{
				int j=e[i];
				if(dist[j]>dist[t]+w[i])
				{
					dist[j]=dist[t]+w[i];
					if(st[j]==false)
					{
						st[j]=true;
						q.offer(j);
					}
				}
			}
		}
	}


if(dist[n]>INF/2)

spfa判断负环

	static Queue q=new LinkedList();
	static boolean spfa()
	{
		for(int i=1;i<=n;++i){
			st[i]=true;
			q.offer(i);
		}
		while(!q.isEmpty())
		{
			int t=(int)q.poll();
			st[t]=false;
			for(int i=h[t];i!=-1;i=ne[i])
			{
				int j=e[i];
				if(dist[j]>dist[t]+w[i])
				{
					dist[j]=dist[t]+w[i];
					cnt[j]=cnt[t]+1;
					if(cnt[j]==n)return true;
					if(st[j]==false)
					{
					    q.offer(j);
					    st[j]=true;
					}
				}
			}
		}
		return false;
	}

floyd

初始化,建图,算法,判断用if(dist[a][b]>INF/2)

import java.util.*;

public class Main
{
	static int n,m,k,N=205,INF=0x3f3f3f3f;
	static int dist[][]=new int [N][N];
	static void floyd()
	{
		for(int k=1;k<=n;++k)
			for(int i=1;i<=n;++i)
				for(int j=1;j<=n;++j)
				{
					dist[i][j]=Math.min(dist[i][j], dist[i][k]+dist[k][j]);
				}
	}
	public static void main(String args[])
	{
		Scanner sc=new Scanner(System.in);
		n=sc.nextInt();
		m=sc.nextInt();
		k=sc.nextInt();
		for(int i=1;i<=n;++i)
			for(int j=1;j<=n;++j)
				if(i!=j)dist[i][j]=INF;
		
		for(int i=0;i<m;++i)
		{
			int a,b,c;
			a=sc.nextInt();
			b=sc.nextInt();
			c=sc.nextInt();
			dist[a][b]=Math.min(dist[a][b], c);
		}
		floyd();
		for(int i=0;i<k;++i)
		{
			int a,b;
			a=sc.nextInt();
			b=sc.nextInt();
			if(dist[a][b]>INF/2)System.out.println("impossible");
			else
			System.out.println(dist[a][b]);
		}
	}
}
posted @ 2022-11-17 23:03  林动  阅读(25)  评论(0编辑  收藏  举报