图论

博客主要介绍图论相关知识,包括图的定义、分类(无向图、有向图、带权图),图的表示方法(邻接矩阵、邻接表),图的搜索(主要通过DFS)以及最短路径问题(单源最短路径),还给出相关例题,最后分享比赛经历与反思。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

图论
一、什么是图
1、图是(vertex,node顶点(edge)组成。
2、分类
(1)无向图(无指向)
例如:亲属关系,路程图
(2)有向图(边有指向)
例如:流程图
(3)带权图(边上带权值)
权值可表示时间、价值等
———无向图
1、如果两顶点之间有边连接,那么视两顶点相邻,相邻结点的序列称为路径。起点和终点重合的称为。任意两点都有路径连接,称为连通。顶点连接的边数称为顶点的度。
2、没有圈的连通图称为树,
———有向图
1、以顶点为起点的边的集合的大小称为顶点的入度,为终点的大小为出度。没有圈的有向图称为DAG
二、图的表示
1、邻接矩阵
把边和结点用具体的数据结构保存下来,主要有邻接矩阵和邻接表。
使用二维数组来表示,个g[i][j]来表示顶点i和j关系。如果i和j连接值就为1,否则为0.无向图g[i][j]=g[j][i],有向图只需标注g[i][j].带权值使g[i][j]值为权值,0仍为权值,无连接为INF。
2、邻接表
表示从顶点到其他点边数集合
例:g[v].push_back(e)//顶点v,其他顶点e。
3、点多边比较稀疏的时候使用邻接表,但实现复杂,并且不易遍历。
三、图的搜索
主要通过DFS实现
例题:
给定一个具有n个顶点的图,相连的两顶点不同色,是否能实现?

#include <iostream>
#define MAX 1000
int Graph[MAX][MAX];//存储图的序号
int color[MAX];//存储各个顶点的颜色  1或-1
using namespace std;
int dfs(int point,int c)//把点point染成c色,并且从顶点point开始深度搜索,如果不满足就返回0
{
    color[point] = c;
    int i;
    for(i = 1;i <= Graph[point][0];i++) //对每一个相邻顶点判断
    {
        // 如果相邻顶点的颜色相同,则返回0
        if(color[Graph[point][i]] == c)  return 0;
        // 如果相邻顶点还没有染色,则染成-c,并深度搜索判断真假
        if(color[Graph[point][i]] == 0 && !dfs(Graph[point][i],-c)) return 0;
    }
    //如果所有顶点都满足,就返回1
    return 1;
}
int main(void)
{
    int N,i,j,flag = 1; // N是图顶点个数
    cin>>N;

    for(i = 0;i < N;i++){
        cin>>Graph[i][0];  //用Graph[i][0]来存储相邻顶点个数 
        for(j = 1;j <= Graph[i][0];j++){
            cin>>Graph[i][j];
        }
    }  //读取图

    for(i = 0;i < N;i++){
        if(color[i] == 0) //如果点i还没有染色,就染成1
        {
            if(!dfs(i,1)){  //如果判断为假,则退出
                cout<<"NO";
                flag = 0;
                break;
            }
        }
    }

  if(flag == 1) //如果判断为真,则输出YES
        cout<<"YES";

    return 0;
}

四、最短路径
1、单源最短路径问题。
固定起点求他到其他点最短路径。d[v]表示起点到V顶点距离。
实现代码

#include <iostream>
#define MAX_E 1000
#define INF 1e9
using namespace std;
struct edge{int from,int to,int cost};
edge es[MAX_E];//边的集合
int d[MAX_E];//最短距离
int v,e;//顶点和边
void shortpath(int s)//s为起点
{
    for(int  i=0;i<v;i++) d[i]=INF;
    d[s]=0;
    while(true)//
    {
        bool update=false;
        for(int i=0;i<e;i++)//遍历所有边
        {
            egde e=es[i];
            if(d.[e.from]!=INF&&d[e.to]>d[e.from]+e.cost))
            {
                d[e.to]=d[e.from]+e.cost;
                update=true;
            }
        }
        if(!uopdate) break;//不再能更新,找出所有起点到其他顶点最短路径。
    }
}

最近总结
今天还是跟着做了一场比赛,一如既往的糟糕,心态快炸了,做到3个小时的时候,提交六个题,只上传成功一个,其他全部pending,当时快感觉做不下去了,看了榜单,QAQ。队友打气最后还是硬着头皮做了。题目的思维题,总是搞错,总想着暴力枚举,递归出奇迹,下次一定要多读题,多思考。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值