基本图算法
广度优先搜索(BFS)
BFS解决图的连通问题(杭电15年复试真题)
//用BFS计算矩阵中连通块数
import java.util.Queue;
import java.util.Scanner;
import java.util.LinkedList;
public class Main {
static int m, n;//m*n的矩阵
static int num[][];//存放矩阵内容
static int X[], Y[];//控制枚举四个方向
static boolean inq[][];//标记是否进过队列
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
m = in.nextInt();
n = in.nextInt();
num=new int[m][n];
for (int i = 0; i < m; i++)
for (int j = 0; j < n; j++)
num[i][j] = in.nextInt();
X = new int[4];
Y = new int[4];
X[0] = 0;
X[1] = 0;
X[2] = 1;
X[3] = -1;
Y[0] = 1;
Y[1] = -1;
Y[2] = 0;
Y[3] = 0;
inq = new boolean[m][n];
for (int i = 0; i < m; i++)
for (int j = 0; j < n; j++)
inq[i][j] = false;
int ans = 0;
for (int x = 0; x < m; x++) {
for (int y = 0; y < n; y++) {
if (num[x][y] == 1 && inq[x][y] == false) {
ans++;//连通块数
BFS(x, y);//广度优先遍历算法
}
}
}
System.out.println(ans);
}
private static void BFS(int x, int y) {
Queue<Node> Q=new LinkedList<Node>();
Node node = new Node(x, y);
Q.offer(node);//入队
inq[x][y] = true;//标记入队
while (!Q.isEmpty()) {
Node top = Q.peek();//取出队首元素
Q.poll();//队首元素出队
for (int i = 0; i < 4; i++) {
int newX = top.x + X[i];
int newY = top.y + Y[i];
if (judge(newX, newY)) {//判断是否出界或者是否访问
过
node = new Node(newX, newY);
Q.offer(node);
inq[newX][newY] = true;
}
}
}
}
private static boolean judge(int x, int y) {
if (x >= m || x < 0 || y >= n || y < 0)
return false;
if(num[x][y]==0||inq[x][y]==true)
return false;
return true;
}
}
class Node {
int x, y;
public Node(int x, int y) {
this.x = x;
this.y = y;
}
}//x,y分别表示节点的横纵坐标
BFS算法用于迷宫求解问题(最小步数)
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
public class Main{
static int n,m;
static char ch[][];
static int X[];
static int Y[];
static boolean inq[][];//元素是否已如果队 不是元素是否依被访问过
static Node S,T,node;
public static void main(String[] args) {
Scanner in=new Scanner(System.in);
n=in.nextInt();
m=in.nextInt();
ch=new char[n][m];
for(int x=0;x<n;x++) {
String str=in.next();
for(int y=0;y<m;y++) {
ch[x][y]=str.charAt(y);
}
}
S=new Node(in.nextInt(),in.nextInt(),0);
T=new Node(in.nextInt(),in.nextInt());
node=new Node();
X=new int[4];
Y=new int[4];
X[0]=0;
X[1]=0;
X[2]=1;
X[3]=-1;
Y[0]=1;
Y[1]=-1;
Y[2]=0;
Y[3]=0;
inq=new boolean[n][m];
inq[S.x][S.y]=true;
int ans=0;
ans=BFS();
System.out.println(ans);
}
private static int BFS() {
Queue<Node>Q=new LinkedList<Node>();
Q.offer(S);
while(!Q.isEmpty()) {
Node top=Q.peek();
Q.poll();
if(top.x==T.x&&top.y==T.y)
return top.step;
for(int i=0;i<4;i++) {
int newX=top.x+X[i];
int newY=top.y+Y[i];
if(test(newX,newY)) {
node=new Node(newX,newY,top.step+1);
Q.offer(node);
inq[newX][newY]=true;
}
}
}
return -1;
}
private static boolean test(int x, int y) {
if(x<0||x>=n||y<0||y>=m)
return false;
if(ch[x][y]=='*'||inq[x][y]==true)
return false;
return true;
}
}
class Node{
int x,y;
int step;
public Node(int x,int y){
this.x=x;
this.y=y;
}
public Node(int x,int y,int step){
this.x=x;
this.y=y;
this.step=step;
}
public Node() {
}
}
深度优先搜寻(DFS)
Travel Plan问题(PAT A1030)(DFS+Dijkstra)
import java.util.Scanner;
public class Main{
static int n,m,st,de,k;
static int INF=1000000000;
static int G[][],Weight[][];
static int d[],w[];
static boolean vis[];
static int pre[];//存放路径
public static void main(String[] args) {
Scanner in=new Scanner(System.in);
n=in.nextInt();
m=in.nextInt();
st=in.nextInt();
de=in.nextInt();
G=new int[n][n];
Weight=new int[n][n];
w=new int[n];
d=new int[n];
pre=new int[n];
k=0;
vis=new boolean[n];
for(int i=0;i<n;i++)
for(int j=0;j<n;j++) {
G[i][j]=INF;
}
int c1,c2,a,b;
for(int i=0;i<m;i++) {
c1=in.nextInt();
c2=in.nextInt();
a=in.nextInt();
b=in.nextInt();
G[c1][c2]=a;
Weight[c1][c2]=b;
}
Dijkstra(st);
DFS(de);
System.out.printf("%d %d",d[de],w[de]);
}
private static void Dijkstra(int s) {
for(int i=0;i<n;i++)
d[i]=INF;
d[s]=0;
for(int i=0;i<n;i++)
w[i]=INF;
w[s]=0;
for(int i=0;i<n;i++) {
int u=-1;
int min=INF;
for(int j=0;j<n;j++) {
if(vis[j]==false&&d[j]<min) {
u=j;
min=d[j];
}
}
if(u==-1)
return;
vis[u]=true;
for(int v=0;v<n;v++) {
if(vis[v]==false&&G[u][v]!=INF) {
if(d[u]+G[u][v]<d[v]) {
d[v]=d[u]+G[u][v];
w[v]=w[u]+Weight[u][v];
pre[v]=u;
}
else if(d[u]+G[u][v]==d[v]) {
if(w[u]+Weight[u][v]<w[v]) {
w[v]=w[u]+Weight[u][v];
pre[v]=u;
}
}
}
}
}
}
static void DFS(int v) {
if(v==st) {
System.out.printf("%d ",v);
return;
}
DFS(pre[v]);
System.out.printf("%d ",v);
}
}
最小生成树
Prim算法
算法思路基本同Dijkstra算法 只是d[]数组的含义不同
import java.util.Scanner;
public class Main{
static int n,m;
static int G[][];
static int d[];
static int INF=1000000000;
static boolean vis[];
public static void main(String[] args) {
Scanner in=new Scanner(System.in);
n=in.nextInt();
m=in.nextInt();
G=new int[n][n];
d=new int[n];
vis=new boolean[n];
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
G[i][j]=INF;
for(int i=0;i<m;i++) {
int u=in.nextInt();
int v=in.nextInt();
int w=in.nextInt();
G[u][v]=w;
G[v][u]=w;//无向图
}
int ans=prim();
System.out.println(ans);
}
public static int prim() {
for(int i=0;i<n;i++)
d[i]=INF;
d[0]=0;
int ans=0;
for(int i=0;i<n;i++) {
int u=-1;
int MIN=INF;
for(int j=0;j<n;j++) {
if(vis[j]==false&&d[j]<MIN) {
u=j;
MIN=d[j];
}
}
if(u==-1)
return -1;
vis[u]=true;
ans+=d[u];//ans表示权值
for(int v=0;v<n;v++) {
if(vis[v]==false&&G[u][v]!=INF&&G[u][v]<d[v])
d[v]=G[u][v];
}
}
return ans;
}
}
Kruskal算法
import java.util.Arrays;
import java.util.Comparator;
import java.util.Scanner;
public class Main{
static int n,m;
static int father[];//并查集
static Edge e[];
public static void main(String[] args) {
Scanner in=new Scanner(System.in);
n=in.nextInt();
m=in.nextInt();
e=new Edge[m];
father=new int[n];
for(int i=0;i<m;i++) {
int u=in.nextInt();
int v=in.nextInt();
int w=in.nextInt();
e[i]=new Edge(u,v,w); //边类的构造方法
}
int ans=kruskal(n,m);//kruskal算法的入口
System.out.println(ans);
}
private static int kruskal(int n, int m) {
int ans=0;//权值
int Num_Edge=0;//目前的最小生成树的边数
for(int i=0;i<n;i++)
father[i]=i;//初始化并查集
Arrays.sort(e, new Comparator<Edge>() {
@Override
public int compare(Edge o1,Edge o2) {//o2是第一个 o1是第二个
if(o1.cost>o2.cost) return 1;//第二个大于第一个时 true 故是从小到大
else return -1;
}
});//自定义类排序(从小到大)
for(int i=0;i<m;i++) {
int faU=findFather(e[i].u);
int faV=findFather(e[i].v);
if(faU!=faV) {
father[faU]=faV;
ans+=e[i].cost;
Num_Edge++;
if(Num_Edge==n-1) break;
}
}
if(Num_Edge!=n-1) return -1;
else return ans;
}
private static int findFather(int x) {
int a=x;
while(x!=father[x]) {
x=father[x];
}
while(a!=father[a]) {
int z=a;
a=father[a];
father[z]=x;
}//路径压缩
return x;
}
}
class Edge{
int u,v;
int cost;
public Edge(int u,int v,int cost) {
this.u=u;
this.v=v;
this.cost=cost;
}
}
最短路径
Dijkstra算法
import java.util.Scanner;
public class Main{
static int INF=1000000000;
static int G[][];
static int n,m,s;
static int d[];
static boolean vis[];
public static void main(String[] args) {
Scanner in=new Scanner(System.in);
int u,v,w;
n=in.nextInt();//n个顶点
G=new int[n][n];
d=new int[n];
vis=new boolean[n];
m=in.nextInt();//m条边
s=in.nextInt();//起点
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
G[i][j]=INF;
for(int i=0;i<m;i++) {
u=in.nextInt();//边的顶点
v=in.nextInt();//边的终点
w=in.nextInt();//边的权重
G[u][v]=w;//存入矩阵
}
Dijkstra(s);//从起点s开始调用Dijkstra算法
for(int i=0;i<n;i++)
System.out.printf("%d ",d[i]);
}
public static void Dijkstra(int s) {
for(int i=0;i<n;i++)
d[i]=INF;
d[s]=0;
for(int i=0;i<n;i++) {
int u=-1;
int MIN=INF;
for(int j=0;j<n;j++) {
if(vis[j]==false&&d[j]<MIN) {//找到未访问的顶点中
d[]最小的
u=j;
MIN=d[j];
}
}
if(u==-1)
return;
vis[u]=true;
for(int v=0;v<n;v++) {
if(vis[v]==false&&G[u][v]!=INF&&d[u]+G[u][v]<d[v])
d[v]=d[u]+G[u][v];//优化d[v]
}
}
}
}
Emergency(Dijkstra)(PAT A1003)
import java.util.Scanner;
public class Main{
static int n,m,c1,c2;
static int d[],w[],num[],weight[];//num 最短路径数 w最大权值
static boolean vis[];
static int G[][];
static int INF=1000000000;
public static void main(String[] args) {
Scanner in=new Scanner(System.in);
int u,v,l;
n=in.nextInt();
m=in.nextInt();
c1=in.nextInt();
c2=in.nextInt();
d=new int[n];
vis=new boolean[n];
w=new int[n];
num=new int[n];
weight=new int[n];
G=new int[n][n];
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
G[i][j]=INF;
for(int i=0;i<n;i++)
weight[i]=in.nextInt();
for(int i=0;i<m;i++) {
u=in.nextInt();
v=in.nextInt();
l=in.nextInt();
G[u][v]=l;
}
Dijkstra(c1);
System.out.printf("%d %d",num[c2],w[c2]);
}
private static void Dijkstra(int s) {
for(int i=0;i<n;i++)
d[i]=INF;
d[s]=0;
for(int i=0;i<n;i++)
num[i]=0;
num[s]=1;
for(int i=0;i<n;i++)
w[i]=0;
w[s]=weight[s];
for(int i=0;i<n;i++) {
int u=-1;
int min=INF;
for(int j=0;j<n;j++) {
if(vis[j]==false&&d[j]<min) {
u=j;
min=d[j];
}
}
if(u==-1)
return;
vis[u]=true;
for(int v=0;v<n;v++) {
if(vis[v]==false&&G[u][v]!=INF) {
if(d[u]+G[u][v]<d[v]) {
d[v]=d[u]+G[u][v];
w[v]=w[u]+weight[v];
num[v]+=num[u];
}
else if(d[u]+G[u][v]==d[v]) {
if(w[u]+weight[v]>w[v]) {
w[v]=w[u]+weight[v];
}
num[v]+=num[u];
}
}
}
}
}
}