图论 拓扑排序 最短路 的几个模板(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]);
}
}
}