首页 > 其他分享 >10.23 闲话

10.23 闲话

时间:2024-10-24 16:48:54浏览次数:6  
标签:node 10.23 int 闲话 短路 遍历 权值 dp

10.23 闲话 图论复习

还有2天就复赛了,现在暂时不知道做啥题了,写一下这两天复习的图论知识。

1.存图方式

(1.) 邻接矩阵

没什么好说的,最简单的存图方式,一眼就会。

定义矩阵数组 \(a[n][n](n为点的数量数)\) ,\(a[u][v]=w\) 代表 \(u,v\) 之间存在一条权值为 \(w\) 的路径。

由于采用二维数组存图,导致其在稠密图中效率低下,会有很多空间被浪费掉,限制了其发挥。

(2.) \(vector\)

动态数组存图,比较好写也比较常用的一种方式,定义的话为 \(vector<数据类型>a[n](n为点的数量)\) 对于 \(a[u][i]=v\) 来说,其代表点 \(u\) 的第 \(i\) 条边的终点是 \(v\) ,若需存储其权值,则需要改变其数据类型,使用结构体类型。

存储权值的方式以及遍历点 \(i\) 的所有出度的方式。

struct node{
	int id,w; 
};
vector<node>a[maxn];
//向点u压入一条权值为w的通往v的出度
a[u].push((node){v,w});
for(int j=0;j<a[i].size();j++){
	//所有的a[i][j]即为其所有出度
}

比起邻接矩阵存图,其省去了大量的冗余空间存储不存在的边。故其在稠密图的表现明显优于邻接矩阵。

(3.)链式前向星

学的不太好,可能讲起来会比较抽象。

建立结构体数组 \(e[m](m为边的数量)\) 结构体的变量为 \(to(边的终点),next(其同起点的一个兄弟),w(边的权值)\) ,与一个 \(head\) 数组, \(head[i]\) 表示 \(i\) 点的最近一条连边。

存储方式及遍历方法:

struct edge{
    int to,next,w;
}e[m];
int head[n];
void add_edge(int u,int v,int w){  //添加一条由u通向v的权值为w的边
    tot++;               //tot为当前边的编号
	e[tot].to=v;         //边的终点
    e[tot].next=head[u]; //更新其兄弟
    e[tot].w=w;
    head[u]=tot;         //记录u点的最近一条出度
}
//遍历点x的所有出度
for(int i=head[x];i;i=e[i].next){   //最早的点的next值为0
    
}

较起前两种,链式前向星由于不用存储起点,只存储边,不由点决定,决定其空间利用率极高,是最省空间的存图方式。

2.拓扑排序

首先阐述其的定义,在一张 \(DAG(有向无环图)\) 中,若 \(i,j\) 存在一条由 \(i\) 指向 \(j\) 的边,则称 \(j\) 依赖于 \(i\) ,则拓扑排序的目的就是使排序后排在前面的点不依赖于后面的点。

可能有点抽象,形象点来说,就是在一张由有向无环图中,输出入度为零的点,同时将其所连的点的入度减一,重复此过程,直到所有的点都已被输出。这也点出了我们的解决思路,队列存储入度为零的点,当队列非空时,每次取出队首,遍历其所有出度,将其能到达的点的入度减一,若减为零,则将其加入队列,否则继续遍历。

int idx[maxn];                          //入度数组
vector<int>e[n];
queue<int>qu;
for(int i=1;i<=n;i++){
    if(idx[i]==0){
        qu.push(i);
        cout<<i<<" ";
    }
}
while(!qu.empty()){
    int op=qu.top();qu.pop();
    for(int i=0;i<e[op].size();i++){
        int k=a[op][i];
        idx[k]--;
        if(idx[k]==0){
            qu.push(k);
            cout<<k<<" ";
        }
    }
}

3.最短路

很经典的图论问题,也是很常考的知识点。求图上两点的最短路,分为全源最短路及单源最短路两种。

(1.)全源最短路:

全源最短路常使用 \(Floyd\) 算法,其主要思想是通过枚举中继点来缩小路径长度,复杂度为 \(O(n^3)\) 很差,不过相较于对每个点进行一遍寻找单源最短路, \(Floyd\) 算法还是占优势的。

主要采用 \(dp\) 的思想 \(dp[k][i][j]=min(dp[k-1][i][j],dp[k-1][i][k]+dp[k-1][k][j])\) 三维数组效率有点低下,所以使用滚动数组,优化掉第一维 \(dp[i][j]=max(dp[i][j],dp[i][k]+dp[k][j])\) 当然由于使用了滚动数组的原因,导致枚举 \(k\) 的循环必须在 \(i\) , \(j\) 循环的外层。

void flord(){
    for(int k=1;k<=n;k++){
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                dp[i][j]=min(dp[i][j],dp[i][k]+dp[k][j]);
            }
        }
    }
}
//则dp[i][j] 为i点到j点的最短路

(2.)单源最短路

这里是 \(dijkstra\) 算法,一种通过贪心来确定最短路的算法。只能用于无负边权值的图。使用优先队列存储点到起点的距离,对于一个已经在优先队列中的点,若期之前未被遍历过,则遍历其所有出度,更新其可到达的点,若更新后距离更短,则更新距离。

struct edge{
    int u,v;
    int w;
};
vector<edge>e[maxn];  //vector存图
struct node{
    int id,dis;
    bool operator < (const node &x)const{
        return dis<x.dis;
    }
}
int dis[maxn];   //dis记录点i到起点的距离
bool vis[maxn];  //vis代表是否已被确定 
void dijkstra(){
    for(int i=1;i<=n;i++){
        dis[i]=inf;         
        vis[i]=false;       
    }
    dis[s]=0;
    priority_queue<node>pq; 
    pq.push((node){s,0});
    while(!pq.empty()){
        node u=pq.top();pq.pop();
        if(vis[u.id]) continue;
        vis[u.id]=true;
        for(int i=0;i<e[u].size();i++){
            edge k=e[op.id][i];
            if(vis[k.v]) continue;
            if(dis[k.v]>y.w+u.dis){
                dis[k.v]=y.w+u.dis;
                q.push((node){k.v,dis[y.v]});
            }
        }
    }
}

4.最小生成树

最小生成树( \(MST\) ),在图上,联通所有点且不含回路的子图称为一颗生成树,其中边权和最小的称为最小生成树。

这里使用 \(kruskal\) 算法,由于需要连接每一个点,所以可以使用贪心的思路,对所有的边进行排序。选出其中较小的,维护一个并查集,存储已经加入最小生成树的点,维护一个点的集合,直到每一条边都已经遍历。

struct node{
    int u,v,w;     //边集数组u:起点 v:终点 w:权值
}e[maxn];
bool cmp(node a,node b){return a.w<b.w;} //按权值大小排序
int fa[maxn];
int find(int x){
    if(fa[x]==x) return x;
    return fa[x]=find(fa[x]);
}
void merge(int x,int y){
    int f1=find(x),f2=find(y);
    if(fa!=f2){
        fa[f1]=f2;
    }
}
int kruskal(){
    for(int i=1;i<=n;i++) fa[i]=i;
    int ans=0;
    sort(e+1,e+1+m,cmp);
    for(int i=1;i<=m;i++){
        int u=e[i].u,v=e[i].v;
        if(find(u)==find(v)) continue;
        merge(u,v);
        ans+=e[i].w;
    }
    return ans;
}

总结

大概先写到这,图论就学到这了,确实不多,还不一定熟练觉得有点悬。

S组复赛祝好。

标签:node,10.23,int,闲话,短路,遍历,权值,dp
From: https://www.cnblogs.com/adsd45666/p/18499910

相关文章

  • 团队练习记录2024.10.23
    比赛链接:https://codeforces.com/gym/104976D.OperatorPrecedence队友解的,想办法让第二个式子中括号内数值为1,所以就2,-1交替,最后一个选1可逆推,第一个为2*n-3#include<iostream>#include<queue>#include<map>#include<set>#include<vector>#include<algorithm>#inc......
  • 2024.10.23
      今天有些小忙。  中午和陈处去吃了一直久闻大名的铁锅炖,遗憾地发现其实也不过如此。吃饭时路上偶然谈到冬旭,算起来他已经走了1年半有余,而离我收到讣告几乎刚好一年。中间相差的半年,陈处一直不告诉我,这一点我至今不太能理解。可能那时候他真的,一想起此事就控制不住自......
  • 2024.10.23总结+CSP2024前总结
    赛时T1看完一脸懵逼啊,画了好几个立方体,一直觉得切四刀是14块,然后也找不到什么规律,就去看后面的题了,jsy说是15之后还是没想法,只觉着\(7=2^3-1\),\(15=2^4-1\),当\(n<=m\)时是\(2^n\),后来看回来把已知情况全列出来,找到\(f[i][j]=f[i][j-1]+f[i-1][j-1]\)的递推式,写了60pts的,但WA了......
  • 10.23日
    DDLDDL用于定义和管理数据库的结构。常见的DDL操作包括:创建表:使用CREATETABLE创建新表。修改表:使用ALTERTABLE修改表的结构,例如添加或删除列。删除表:使用DROPTABLE删除表及其所有数据。sqlCREATETABLEStudents(IDINTPRIMARYKEY,NameVARCHAR(100),Ag......
  • 10.23随笔
    这里是10.23随笔。今天我又发现了一种不一样的解题方法,题是昨天的题,这个方法是迭代,代码留档:intdegreeOneNodesIterative(structTreeNode*root){if(root==NULL){return0;}intcount=0;structTreeNode*current;SqQueuequeue;InitQueue(&queue);EnQueue(&qu......
  • 2024.10.23训练记录
    上午NOIP模拟A简单题。类比树状数组,反向做二维前缀和。在数组中对于左上角为{x_1,y_1},右下角为{x_2,y_2}的矩阵实现+k操作。只需要在{x_1,y_1},{x_2+1,y_2+1}位置+k,{x_2+1,y_1},{x_1,y_2+1}位置-k。最后再做一遍二维前缀和。很好想到的。想到是应该的。考试......
  • 2024.10.23 在不同的阶段反复爱上罗大佑的词曲
      我这一生真是会在不同阶段,反复爱上罗大佑这位音乐人.  小时候听的《童年》,长大之后才知道是写给已经失去童年的人的,没有办法让孩子真正听懂。  后来逐渐地,求学于鳌峰时,在《滚滚红尘》中听出了来易来去难去,分易分聚难聚;求学于石室时,从《鹿港小镇》中听出了台北不是......
  • 10.23 记录
    一些鲜花:自从zcl把我加到了高一小朋友们的团队里,我就能在机房听到一些关键词,包括但不限于:“bug是谁”“M-o-y-y-e-r-s-u-i-y”(大声的念id)“真不愧时他的儿子!”刚才发了一本鸭子的《CSP防爆0手册》,看得津津有味。今天一天没干啥,一个是补了昨天的题。zcl给我讲了t2......
  • 10.22-10.23
    A.异或和CF1261F做过类似的题的话,\(O(n^2\log^2v\log(n^2\log^2v))\)应该算是暴力分了。显然这过不了,不然就不是*3100了。主要的瓶颈在于异或完后产生了大量的线段,而且里面大多数是没用的。于是赛时写出了一个绝唐的优化点击查看代码for(inti=0;i<seg[0].size();......
  • 2024.10.23总结
    本文于github博客同步更新。A:场上唐了。对于每个\(n\),记录能够用\(a\)个\(+\)号与\(b\)个\(\times\)号组成\(n\)的这些\((a,b)\)对,如果某两个对\(\left(a_{1},b_{1}\right),\left(a_{2},b_{2}\right)\)满足\(a_{1}\leqa_{2}\)且\(b_{1}\leqb_{2}\)......