图论笔记1

1.1邻接矩阵储存法

c 复制代码
//创建:二维数组
    vector<vector<int>> graph(n,vector<int>(n,0));
    
//储存
    for(int i=0;i<m;i++){
        int x1,x2;
        cin>>x1>>x2;
        graph[x1-1][x2-1]=1;
    }

1.2邻接表储存法

补充:c++中的list是链表 链接

c 复制代码
//创建:数组+链表
vector<list<int>> graph(n + 1);

//输入
while (m--) {
    cin >> s >> t;
    // 使用邻接表 ,表示 s -> t 是相连的
    graph[s].push_back(t);
}
//读取数据
if (result.size() == 0) cout << -1 << endl;
    for (const vector<int> &pa : result) {
        for (int i = 0; i < pa.size() - 1; i++) {
            cout << pa[i] << " ";
        }
        cout << pa[pa.size() - 1]  << endl;
    }

2.1 dfs

所有可达路径

dfs三部曲:

确认递归函数和参数、确认终止条件、处理目前搜索节点的出发路径(处理节点、dfs递归、回溯)

c 复制代码
#include<iostream>
#include<vector>
using namespace std;

vector<vector<int>> results;
vector<int> result;


//1 确认递归函数参数: 邻接表,当前历遍节点,终点
void dfs(const vector<vector<int>>& graph,int x,int n){
    //2 确认终止条件:当当前节点x = 最后一个节点n,就是从起点到了终点
    if(x==n-1){
        results.push_back(result);//存入结果
        return;
    }
    //3、处理目前搜索节点的出发路径
    for(int i=0;i<n;i++){
        if(graph[x][i]){            //找到下一个节点
            result.push_back(i+1);  //处理节点
            dfs(graph,i,n);         //处理下一个节点
            result.pop_back();      //利用vector的性质回溯
        }
    }
}

int main(){
    int n,m;
    cin>>n>>m;
    
    vector<vector<int>> graph(n,vector<int>(n,0));
    
    for(int i=0;i<m;i++){
        int x1,x2;
        cin>>x1>>x2;
        graph[x1-1][x2-1]=1;
    }
    
    
    result.push_back(1); //重要!先把开始节点放进去
    dfs(graph,0,n);
    
    if(results.size()==0)cout<<"-1"<<endl;
    for(int i=0;i<int(results.size());i++){
        for(int j=0;j<int(results[i].size()-1);j++){
            cout<<results[i][j]<<" ";
        }
        cout<<results[i][results[i].size()-1]<<endl;
    }
    
}

要注意0的问题。(开辟n个位置从0-n-1,开辟n+1个位置从0-n)

c 复制代码
#include<iostream>
#include<vector>
#include<list>
using namespace std;

vector<vector<int>> results;
vector<int> result;


//1 确认递归函数参数: 邻接表,当前历遍节点,终点
void dfs(const vector<list<int>>& graph,int x,int n){
    //2 确认终止条件:当当前节点x = 最后一个节点n,就是从起点到了终点
    if(x==n-1){
        results.push_back(result);//存入结果
        return;
    }
    //3、处理目前搜索节点的出发路径
    for(int i:graph[x]){            //找到下一个节点
            result.push_back(i+1);  //处理节点
            dfs(graph,i,n);         //处理下一个节点
            result.pop_back();      //利用vector的性质回溯
    }
}

int main(){
    int n,m;
    cin>>n>>m;
    
    vector<list<int>> graph(n);
    
    for(int i=0;i<m;i++){
        int x1,x2;
        cin>>x1>>x2;
        graph[x1-1].push_back(x2-1);
    }
    
    
    result.push_back(1); //重要!先把开始节点放进去
    dfs(graph,0,n);
    
    if(results.size()==0)cout<<"-1"<<endl;
    for(int i=0;i<int(results.size());i++){
        for(int j=0;j<int(results[i].size()-1);j++){
            cout<<results[i][j]<<" ";
        }
        cout<<results[i][results[i].size()-1]<<endl;
    }
    
}

岛屿问题99

c 复制代码
#include<iostream>
#include<vector>
using namespace std;

//1、确定参数
void dfs(const vector<vector<int>>& graph,vector<vector<int>>& visited, int x, int y){
   int dir[4][2]={0,1,  1,0,  -1,0,  0,-1};
    
    //2、终止条件(访问过了/周边都是0了,一条路就走完了)
    if(visited[x][y] || graph[x][y]==0) return;
    //3、处理当前点
    visited[x][y]=1;
    for(int i=0;i<4;i++){//上下左右四个位置,作用是感染同一岛屿的所有块(颜色填充也是这个原理)
        int newx=x+dir[i][0];
        int newy=y+dir[i][1];
        if(newx<0||newx>=int(graph.size())||newy<0||newy>=int(graph[0].size())) continue;
        dfs(graph,visited,newx,newy);
    }
    
}

int main(){
    int n,m;
    cin>>n>>m;
    vector<vector<int>> graph(n,vector<int>(m,0));
    for(int i=0;i<n;i++){
        for(int j=0;j<m;j++){
            cin>>graph[i][j];
        }
    }
    
    // for(int i=0;i<n;i++){
    //     for(int j=0;j<m;j++){
    //         cout<<graph[i][j]<<" ";
    //     }
    //     cout<<endl;
    // }
    vector<vector<int>> visited(n,vector<int>(m,0));
    int result=0;
    
    for(int i=0;i<n;i++){
        for(int j=0;j<m;j++){
            if(!visited[i][j] && graph[i][j]==1){
                dfs(graph,visited,i,j);
                result++;
            }
        }
    }
    cout<<result;
}

岛屿最大面积100

c 复制代码
#include<iostream>
#include<vector>
using namespace std;

//1、确定参数(注意!!这里visited和single想要被改变,要传入变量本身!要用&)
void dfs(const vector<vector<int>>& graph,vector<vector<int>>& visited,int x,int y,int& single){
    //2、停止条件
    if(graph[x][y]==0||visited[x][y]){return;}
    
    //3、处理当前节点
    single++;
    visited[x][y]=1;
    int dir[4][2]={0,-1,0,1,-1,0,1,0};
    for(int i=0;i<4;i++){
        int newx=x+dir[i][0];
        int newy=y+dir[i][1];
        if(newx<0||newx>=int(graph.size())||newy<0||newy>=int(graph[0].size())) continue;
        dfs(graph,visited,newx,newy,single);
    }
}

int main(){
    int n,m;
    cin>>n>>m;

    vector<vector<int>> graph(n,vector<int>(m,0));
    
    for(int i=0;i<n;i++){
        for(int j=0;j<m;j++){
            cin>>graph[i][j];
        }
    }
    
    int result=0;
    vector<int> s;
    vector<vector<int>> visited(n,vector<int>(m,0));
    for(int i=0;i<n;i++){
        for(int j=0;j<m;j++){
            if(!visited[i][j] && graph[i][j]==1){
                int single=0;
                dfs(graph,visited,i,j,single);
                result=max(result,single);
            }
        }
    }
    
    cout<<result;
    
    
}

2.2 最小生成树

prim

c 复制代码
#include<iostream>
#include <vector>
#include <climits>
using namespace std;

int main(){
    int v,e;
    cin>>v>>e;
    
    vector<vector<int>> graph(v+1,vector<int>(v+1,100001));
    
    while(e--){
        int x1,x2,val;
        cin>>x1>>x2>>val;
        graph[x1][x2]=val;//是无向图
        graph[x2][x1]=val;
    }
    //------------------检查用----------------------------
    // for(int i=1;i<=v;i++){
    //     for(int j=1;j<=v;j++){
    //         cout<<graph[i][j]<<" ";
    //     }
    //     cout<<endl;
    // }
    //----------------------------------------------------
    
    vector<int> minDist(v+1,100001);
    vector<int> intree(v+1,false);
    vector<int> arc(v+1);
    int start=-1;
   
    for(int count=1;count<v;count++){//循环n-1次
        //1、选距离生成树最近的节点,即更新start
        int min=INT_MAX;
        for(int i=1;i<=v;i++){
            if(!intree[i] && minDist[i]<min) {//这里是算生成树的每个节点与离它最近的树外节点的距离
                min=minDist[i];
                start=i;
            }
        }
        
        if(start==-1) {cout<<"-1"<<endl;return 0;}
        //把最近的节点加入生成树
        intree[start]=1;
        
        //------------------检查用----------------------------
        // for(int i=1;i<=v;i++){
        //     cout<<minDist[i]<<" ";
        // }
        // cout<<"###################"<<endl;
        //----------------------------------------------------
        
        //3、更新非生成树节点到生成树的距离,即minDist数组。并记录1中最短边,即更新arc数组
        for(int j=1;j<=v;j++){
            if(!intree[j] && graph[start][j]<minDist[j]){//只要一端在start,另一端不在树里,且值比当前位置值小的,都放进来
                minDist[j]=graph[start][j];
                arc[j]=start;
            }
        }
        
        //------------------检查用----------------------------
        // for(int i=1;i<=v;i++){
        //     cout<<minDist[i]<<" ";
        // }
        // cout<<"-------------------"<<endl;
        //----------------------------------------------------
        
        
    }
    
     int total=0;
    for(int i=2;i<=v;i++){
       total+=minDist[i];
    }
    cout<<total<<endl;
}
相关推荐
19999er2 小时前
CDN信息收集(小迪网络安全笔记~
服务器·网络·笔记·安全·web安全
红色的山茶花2 小时前
YOLOv9-0.1部分代码阅读笔记-dataloaders.py
笔记·深度学习·yolo
UQI-LIUWJ2 小时前
datasets 笔记:加载数据集(基本操作)
笔记
1101 11014 小时前
STM32-笔记9-电动车报警器
笔记
饮食有度的元气少女4 小时前
讲PPT 需要注意的事项
笔记
Allen_LVyingbo5 小时前
量子芯片在新医疗领域的应用研究展望
笔记·健康医疗·集成学习
冷眼看人间恩怨6 小时前
【Qt笔记】QComboBox控件详解
c++·笔记·qt
是小菜呀!6 小时前
实验一 系统认识、基本逻辑门逻辑实验
笔记
UQI-LIUWJ6 小时前
datasets 笔记: 文本数据集的预处理(Tokenization)
人工智能·笔记·深度学习