#include
#include
#include
#include
using namespace std;
const int N=100;
int map[N][N];
bool boo[N];
int dis[N];
int a,b;
int c=0;
int foot[N];
int key1,key2,value;
void dijkstra(int key){
foot[c++]=key;
boo[key]=1;
dis[key]=0;
int tag=key;
for(int i=0;i<a-1;++i){
for(int k1=0;k1<a;k1++){
if(map[tag][k1]!=0 && map[tag][k1]!=INT_MAX && boo[k1]==0 ){
cout<<"dis[k1]:"<<dis[k1]<<endl;
cout<<"dis[tag]:"<<dis[tag]<<endl;
if(dis[k1]==INT_MAX|| dis[tag]+map[tag][k1]<dis[k1]){
dis[k1]=dis[tag]+map[tag][k1];
}
}
}
cout<<"dis:"<<endl;
for(int k=0;k<a;k++){
cout<<dis[k]<<" ";
}
cout<<endl;
cout<<"next:"<<endl;
int next=INT_MAX;
for(int j=0;j<a;j++){
if(boo[j]!=1 && dis[j]!=0 && dis[j]<next){
next=dis[j];
tag=j;
}
}
cout<<"tag:"<<tag<<endl;
boo[tag]=1;
foot[c++]=tag;
}
cout<<endl;
cout<<"foot:"<<endl;
for(int i=0;i<a;i++){
cout<<foot[i]<<"-";
}
cout<<"dis:"<<endl;
for(int i=0;i<a;i++){
cout<<dis[i]<<"-";
}
}
int main(int argc, char *argv[]) {
int G[6][4];
fill(G[0],G[0]+6*4,520);
for(int i=0;i<6;i++){
for(int j=0;j<4;j++){
cout<<G[i][j]<<" ";
}
cout<<endl;
}
cout<<"请输入顶点数和边数:例如 5 6"<<endl;
cin>>a>>b;
fill(map[0],map[0]+N*N,INT_MAX);
fill(dis,dis+a,INT_MAX);
for(int i=0;i<b;i++){
cin>>key1>>key2>>value;
map[key1][key2]=value;
map[key2][key1]=value;
}
for(int i=0;i<b;i++){
for(int j=0;j<b;j++){
if(i==j){
map[i][j]=0;
break;
}
}
}
cout<<"show map:"<<endl;
for(int i=0;i<b;i++){
for(int j=0;j<b;j++){
cout<<map[i][j]<<" ";
}
cout<<endl;
}
dijkstra(0);
return 0;
}
**
floyd
**
1.用所有顶点更新图「二维数组」
2.「当前顶点v iv+vj 3.路径打印使用递归回溯
路径解析:
一开始二维数组所有所有设为-1
更新路径v时说明不是直接通路 是需要桥梁
只有时-1的时候才是直接通路相连的,输出u,v
不是-1则时中间点 递归 左边 递归右边
#include
#include
#include
using namespace std;
const int N=100;
int map[N][N];
void init()
{
for(int i=0; i<N; i++)
{
for(int j=0; j<N; j++)
{
map[i][j]=9999;
}
}
}
void floyd(int n)
{
int i,j,k;
for(int k=0;k<n;k++)
{
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
if(i!=j)
map[i][j]=min(map[i][j],map[i][k]+map[k][j]);
}
}
}
}
void PMap(int n)
{
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
cout<<map[i][j]<<" ";
}
cout<<endl;
}
}
int main()
{
int n,v;
init();
cout<<"请输入顶点数和边数:"<<endl;
cin>>n>>v;
PMap(n);
int key1,key2,cost;
for(int i=0;i<v;i++)
{
cin>>key1>>key2>>cost;
map[key1][key2]=map[key2][key1]=cost;
}
cout<<"input:"<<endl;
PMap(n);
floyd(n);
cout<<"AA:"<<endl;
PMap(n);
return 0;
}
DFS && BFS
遍历图
都要直接遍历所有顶点函数:原因是避免非连通图,不相连的顶点没有遍历
BFS:
从一个顶点v开始
把v顶点的邻接点放入queue中
出队一个,打印一个 重复操作
直到队列为空
#include
#include
#include
using namespace std;
int map[5][5]={
{0,1,0,1,0},
{1,0,1,0,1},
{0,1,0,0,0},
{1,0,0,0,0},
{0,1,0,0,0}
};
bool bmap[5];
queue<int> q;
int count=0;
int foot[5];
void bfs(){
while(!q.empty()){
int key=q.front();
q.pop();
for(int i=0;i<5;i++){
if(bmap[i]==false && map[key][i]==1){
cout<<i+1<<endl;
bmap[i]=true;
foot[count++]=i;
q.push(i);
if(count==5){
exit(0);
}
}
}
}
}
int main(int argc, char *argv[]) {
int key=4;
bmap[key]=true;
foot[count++]=key;
q.push(key);
bfs();
for(int i=0;i<5;i++){
cout<<foot[i]<<"-";
}
cout<<endl;
return 0;
}
DFS:
出口 count==n
key
找邻接点key i==1 「通路」
找到马上递归DFS i 找下一个邻接点
#include
#include
using namespace std;
int map[5][5]={
{0,1,0,1,0},
{1,0,1,0,1},
{0,1,0,0,0},
{1,0,0,0,0},
{0,1,0,0,0}
};
bool bmap[5];
int foot[5];
int count=0;
void dfs(int key){
foot[count++]=key;
if(count==5){
exit(0);
}
bmap[key]=true;
for(int i=0;i<5;i++){
if(bmap[i]==false && map[key][i]==1){
cout<<i+1<<endl;
dfs(i);
}
}
}
int main(int argc, char *argv[]) {
dfs(2);
for(int i=0;i<5;i++){
cout<<foot[i]<<"-";
}
cout<<endl;
return 0;
}
Kruscal:
find函数
union函数
father数组
边集
如果没有顶点编号,给的是坐标,需要自动生成边集,则使用一个顶点 连n个顶点双循环
顶点编号使用i j
for( i=0;i for(j=i+1; j E[num].u=i; E[num].v=j;
E[num].cost=[计算];
num++;
num就是边的数量
sort 边集就可以使用kruscal算法了
#include
#include
using namespace std;
const int N=1000;
struct EDGE{
int u,v,cost;
void set(int a,int b,int w){
u=a;
v=b;
cost=w;
}
};
EDGE edge[N*N-1/2];
bool cmp(EDGE a, EDGE b){
return a.cost<b.cost;
}
int father[N];
int find(int x){
if(father[x]==-1){
return x;
}else{
return father[x]=find(father[x]);
}
}
bool union1(int x ,int y){
x=find(x);
y=find(y);
if(x==y){
return false;
}
if(x>y){
father[x]=y;
}else{
father[y]=x;
}
return true;
}
int main(int argc, char *argv[]) {
int i;
int v,w,cost;
cout<<"请输入边数和顶点数:"<<endl;
int m,t;
cin>>m>>t;
cout<<"请输入边的信息 例如 1 2 10:"<<endl;
for(i=0;i<m;i++){
cin>>v>>w>>cost;
edge[i].set(v,w,cost);
}
sort(edge,edge+m,cmp);
i=0;
fill(father,father+m,-1);
int sum=0,count=0;
while(count!=t-1){
if(union1(edge[i].u,edge[i].v)){
cout<<edge[i].u<<"-"<<edge[i].v<<endl;
sum+=edge[i].cost;
count++;
}
i++;
}
cout<<"sum:"<<sum <<endl;
return 0;
}
**
Prim:
**
1.先从一个顶点v开始 先设置为true
2.更新cost数组
3.进循环 直到count==n-1「所有顶点纳入图中」
4.选最小 并设置true
5.更新cost数组
#include
using namespace std;
const int adjacent_matri_max=1000;
int vertex_num,edge_num;
int price=0;
int adjacent_matri[adjacent_matri_max][adjacent_matri_max];
bool visitied[adjacent_matri_max];
int l_cost[adjacent_matri_max];
int path[adjacent_matri_max];
void init(){
for(int i=0;i<vertex_num;i++){
for(int j=0;j<vertex_num;j++){
adjacent_matri[i][j]=INT_MAX;
}
}
fill(visitied,visitied+vertex_num,false);
fill(l_cost,l_cost+vertex_num,INT_MAX);
return ;
}
void Prim(int key){
int k=0;
path[k++]=key;
do{
visitied[key]=true;
for(int i=0;i<vertex_num;i++){
l_cost[i]=min(l_cost[i],adjacent_matri[key][i]);
}
int min_cost=INT_MAX;
for(int i=0;i<vertex_num;i++){
if(visitied[i]==false && l_cost[i]<min_cost){
min_cost=l_cost[i];
key=i;
}
}
price+=min_cost;
path[k]=key;
cout<<k+1<<":"<<endl;
cout<<"mint_cost:"<<min_cost<<endl;
cout<<"price:" <<price<<endl<<endl;
}while(++k<vertex_num);
return;
}
void PrintTree(int key){
cout<<"最小生成树生成顺序:"<<endl;
int count=0;
for(int i=0;i<vertex_num;i++){
cout<<path[i]<<" ";
}
}
int main(){
int row,col;
int key;
int weight;
cout<<"现在开始构造图:"<<endl;
cout<<"请输入顶点数量:"<<endl;
cin>>vertex_num;
cout<<"请输入边的数量:"<<endl;
cin>>edge_num;
init();
cout<<"请输入边(两个顶点表示)和边的权值:(共"<<edge_num<<"组(行))"<<endl;
for(int i=0;i<edge_num;i++){
cin>>row>>col;
cin>>weight;
adjacent_matri[row][col]=adjacent_matri[col][row]=weight;
}
for(int i=0;i<vertex_num;i++){
for(int j=0;j<vertex_num;j++){
cout<<adjacent_matri[i][j]<<" ";
}
cout<<endl;
}
cout<<"请输入起点顶点:"<<endl;
cin>>key;
Prim(key);
cout<<"最小生成树代价为:"<<price<<endl;
PrintTree(key);
return 0;
}
topologicalsort
:
1.把所有indegree为0的顶点入队
2.当队不为空
获取队头元素,并出队,记录。
使用队头元素找到相邻的边后 使该点入度-1
判断indegree为0入队
--------- 当count为n时 拓扑成功-----------否则 失败 因:成环
#include
#include
#include
using namespace std;
const int N=100;
int map[N][N];
int vis[N];
void topsort(int n)
{
int in;
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
for(int k=0;k<n;k++)
{
if(!vis[k])
{
vis[k]=-1;
in=k;
cout<<k<<endl;
break;
}
}
}
for(int i=0;i<n;i++)
{
if(map[in][i]==1)
{
vis[i]--;
map[in][i]=0;
}
}
}
}
int main()
{
int n,v;
cout<<"请输入顶点数和边数:"<<endl;
cin>>n>>v;
int key1,key2;
for(int i=0;i<v;i++)
{
cin>>key1>>key2;
map[key1][key2]=1;
vis[key2]++;
}
topsort(n);
return 0;
}
求点赞
原创不易,点赞容易。
您的鼓励就是我的最大动力!!!。
本篇博客到此结束,谢谢大家观看。