宽度优先遍历求最短路径
txt文件如下
7 8
1 2
1 4
2 3
4 3
2 6
3 5
4 5
5 7
如图,我们求各节点到节点1的距离,只需在遍历过程增加一个数组存放距离,且在访问节点过程中距离+1即可。注意有向图和无向图皆可。
//无向图宽度优先遍历求最短路径
#include<iostream>
#include<vector>
#include<queue>
#define MAX 100
using namespace std;
vector <int> G[MAX];
int V;
int E;
int d[MAX];
bool visited[MAX];
void bfs(int v);
int min(int a,int b)
{
return a<b?a:b;
}
//宽度优先搜索
void BFS()
{
for(int i = 1;i <= V;i++)
{
if(!visited[i])
bfs(i);
}
}
void bfs(int v)
{
queue <int> que;
que.push(v);
int count = 0;
d[v] = 0;
while(!que.empty())
{
int t = que.front();
visited[t] = true;
que.pop();
int len = G[t].size();
for(int i = 0;i < len;i++)
{
if(!visited[G[t][i]])
{
que.push(G[t][i]);
d[G[t][i]] = min(d[G[t][i]],d[t] + 1);
}
}
}
}
int main()
{
cin >> V >>E;
for(int i = 1;i <= E;i++)
{
int s,t;
cin>>s>>t;
G[s].push_back(t);
// G[t].push_back(s);
}
cout <<"邻接表"<<endl;
for(int i = 1;i <= V;i++)
{
int len = G[i].size();
cout<<i<<"\t";
for(int j = 0;j < len;j++)
cout<<G[i][j]<<" ";
cout<<endl;
}
fill(d,d+V+1,MAX);
cout<<"BFS遍历,各节点对于节点1的距离"<<endl;
BFS();
for(int i = 1;i <= V;i++)
cout<<d[i]<<" ";
return 0;
}
Prim算法求最小生成树
结果
最小生成树是 2+3+1+4+2=12
输入txt文件
6
1 2 2 2 3 3
2 2 6 1 4 6
3 2 4 4 5 7
4 1 5 10
5 1 6 2
6 0
#include<iostream>
#include<cstdio>
#include<vector>
#include<queue>
#define MAX 100
#define INF 1e5
using namespace std;
typedef pair<int,int> P;//权值,顶点
struct edge{int to,cost;};
int V;
int par[MAX];
bool visited[MAX];
vector <edge> G[MAX];
void prim()
{
cout<<"prim algorithm"<<endl;
//初始化
priority_queue <P,vector<P>,greater<P> > que;//从小到大排列
fill(par,par+V+1,-1);
int s = 1;
int sum = 0;
int n = 0;
que.push(P(0,s));
while(n++ < V && !que.empty())
{
P p = que.top();
que.pop();
if(visited[p.second])continue;
sum += p.first;
int v = p.second;
visited[v] = true;
int k = G[v].size();
for(int i = 0;i < k;i++)
{
edge e;
e.to = G[v][i].to;
e.cost = G[v][i].cost;
if(!visited[e.to])
que.push(P(e.cost,e.to));
}
}
cout<<"sum="<<sum<<endl;
}
int main()
{
cin >> V;
for(int i = 1;i <= V;i++)
{
int u,k,v,c;
cin>>u;
cin>>k;
for(int j=0;j<k;j++)
{
cin>>v>>c;
edge e;
e.to=v;e.cost=c;
G[u].push_back(e);
e.to=u;
G[v].push_back(e);
}
}
// for(int i = 1;i <= V;i++)
// {
// int k = G[i].size();
// cout<<i<<" "<<k<<"\t";
// for(int j=0;j<k;j++)
// {
// cout<<G[i][j].to<<" "<<G[i][j].cost<<" ";
// }
// cout<<endl;
// }
prim();
cout<<"done"<<endl;
return 0;
}
Kruskal求最小生成树
图同上
txt文件如下
7 8
1 2 2
1 3 3
2 4 6
2 6 1
3 4 4
3 5 7
4 5 10
5 6 2
//使用kruskal算法,并查集结构求最小生成树
#include<iostream>
#include<vector>
#include<algorithm>
#define MAX 100
using namespace std;
int par[MAX];
int rank[MAX];
struct edge{int u,v,cost;};
edge es[MAX];
int V,E;
void init(int n)
{
for(int i=0;i<n;i++)
{
par[i] = i;
rank[i] = 0;
}
}
int find(int x)
{
if(par[x] == x)
{
return x;
}
else
return par[x] = find(par[x]);
}
void unite(int x,int y)
{
x = find(x);
y = find(y);
if(x == y)
return;
if(rank[x] < rank[y])
par[x] = y;
else{
par[y] = x;
if(rank[x] == rank[y])
rank[x]++;
}
}
bool same(int x,int y)
{
return find(x) == find(y);
}
bool comp(const edge& e1,const edge& e2)
{
return e1.cost < e2.cost;
}
int kruskal()
{
sort(es,es+E,comp);
init(V);
int res = 0;
for(int i = 0;i < E;i++)
{
edge e;
e.u = es[i].u;
e.v = es[i].v;
e.cost = es[i].cost;
if(!same(e.u,e.v))
{
unite(e.u,e.v);
res += e.cost;
cout<<e.u<<"->"<<e.v<<endl;
}
}
return res;
}
int main()
{
cin>>V>>E;
for(int i=0;i<E;i++)
{
edge e;
cin>>e.u>>e.v>>e.cost;
es[i] = e;
}
cout<<kruskal()<<endl;
return 0;
}
选择5条边如下,最小生成树是12
Dijkstra算法求最短路径
图同prim最小生成树
txt文件同prim算法
//dijkstra算法求最短路径
#include<iostream>
#include<vector>
#include<queue>
#define MAX 100
#define INF 1e5
using namespace std;
struct edge{int to,cost;};
typedef pair<int,int> P;//first是最短距离,second是顶点编号
int V;
int d[MAX];
int par[MAX];
vector <edge> G[MAX];
//bool visited[MAX];
void dijkstra()
{
cout<<"dijkstra algorithm"<<endl;
//初始化
int s = 1;
priority_queue <P,vector<P>,greater<P> > que;//从小到大排列
fill(d+1,d+V+1,INF);
// cout<<d[1]<<endl;
d[s] = 0;
par[s] = -1;
que.push(P(0,s));
while(!que.empty())
{
P p = que.top();
que.pop();
int v = p.second;
if(d[v] < p.first)continue;
for(int i = 0;i < G[v].size();i++)
{
edge e = G[v][i];
if(d[e.to] > d[v] + e.cost)
{
d[e.to] = d[v] + e.cost;
que.push(P(d[e.to],e.to));
par[e.to] = v;
}
}
}
for(int i = 1;i<=V;i++)
cout<<d[i]<<" ";
cout<<endl;
}
int main()
{
cin >> V;
for(int i = 1;i <= V;i++)
{
int u,k,v,c;
cin>>u;
cin>>k;
for(int j=0;j<k;j++)
{
cin>>v>>c;
edge e;
e.to=v;e.cost=c;
G[u].push_back(e);
}
}
for(int i = 1;i <= V;i++)
{
int k = G[i].size();
cout<<i<<" "<<k<<"\t";
for(int j=0;j<k;j++)
{
cout<<G[i][j].to<<" "<<G[i][j].cost<<" ";
}
cout<<endl;
}
dijkstra();
cout<<"done"<<endl;
return 0;
}
起点为节点1到各个点的最短距离
分别为0 2 3 7 10 3
拓扑排序算法
txt文件如下
9 12
1 2
2 5
3 2
3 4
4 2
4 6
5 6
5 7
7 6
7 9
6 8
8 9
拓扑序之一:1->3->4->2->5->7->6->8->9
#include<iostream>
#include<cstdio>
#include<vector>
#include<queue>
#define MAX_V 100
using namespace std;
vector<int> G[MAX_V];
int in[MAX_V];
int V,E;
void topo()
{
queue <int>q;
queue <int>ans;
for(int i = 1;i <= V;i++)
{
if(in[i] == 0)
q.push(i);
}
while(!q.empty()){
int t = q.front();
ans.push(t);
q.pop();
int len = G[t].size();
for(int j = 0;j < len;j++)
{
in[G[t][j]]--;
if(in[G[t][j]] == 0)
q.push(G[t][j]);
}
}
int len = ans.size();
for(int i = 0;i < len;i++)
{
cout<<ans.front()<<" ";
ans.pop();
}
cout<<endl;
}
int main()
{
cin >> V;
int n;
cin >> n;
E = n;
while(n--)
{
int i,j;
cin >> i;
cin >> j;
in[j]++;
G[i].push_back(j);
}
topo();
return 0;
}
总结
图算法有很多应用,至于着色问题,二部图匹配,思路本质上一致,不再赘述。
网络流算法如最大流,指派问题,最小路径覆盖,强连通分量问题等仍在学习中,故不提。