首页 > 编程语言 >算法小总结-图论

算法小总结-图论

时间:2024-08-08 19:05:44浏览次数:8  
标签:总结 图论 int head tot vis 算法 edge dis

拓扑排序
[HNOI2015]菜肴制作

//
// Created by fxz on 2024/8/3.
//


#include <bits/stdc++.h>

using namespace  std;


int ans[1008611];
#define int long long


    bool TopSort(vector<vector<int>> &G, int n, vector<int> &inDegree) {
        int cnt=1;
        int num = 0;				//记录加入拓扑排序的顶点数
        priority_queue<int> q;
        for (int i = 1; i <=n; i++)
            if (inDegree[i] == 0)
                q.push(i);		//将所有入度为0的顶点入队
        while (!q.empty()) {
            int u = q.top();		//取队首顶点u
            ans[cnt++]=u;
            q.pop();
            for (int i = 0; i <G[u].size(); i++) {
                int v = G[u][i];		//u的后继节点
                inDegree[v]--;			//v的入度减1
                if (inDegree[v] == 0)		//顶点v的入度减为0则入队
                    q.push(v);
            }
            G[u].clear();			//清空顶点u的所有出边
            num++;
        }
        if (num == n)				//加入拓扑序列的顶点数为n,说明拓扑排序成功,否则,失败
            return true;
        else
            return false;
    }

int32_t main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int t;
    cin>>t;
    while(t--) {
        int n,m;
        cin >> n >>m;
        vector<vector<int>> G(n+1);
        for (int i = 1; i <= m; ++i) {
            int a, b;
            cin >> a >> b;
            G[b].push_back(a);
        }
        vector<int> inDegree(n+1);
        for (auto x : G) {
            for (auto y : x)
                inDegree[y]++;
        }
        bool res = TopSort(G, n, inDegree);
        if(res==0)cout<<"Impossible!"<<'\n';
        else {
            for(int i=n;i>=1;i--){
                cout<<ans[i]<<' ';
            }
            cout<<'\n';
        }
    }

    return 0;

}


Dijkstrra
单源最短路,有向图,无向图都可以用,但是必须是无负权边,每个点都会看一遍
模版如下

#include <bits/stdc++.h>
using namespace std;

typedef pair<int,int> pii;
const int N=1010;
const int M=200010;
int head[N];
int dis[N];
bool vis[N];
int tot;
int n,m,s,t;
struct ty{
    int t,l,next;
}edge[200010];

void add(int x,int y,int z){
    edge[++tot].l=z;
    edge[tot].t=y;
    edge[tot].next=head[x];
    head[x]=tot;
}

struct ty2 {
    int x, dis;
    bool operator<(const ty2 &a) const{
        return dis>a.dis;
    }
};


priority_queue<ty2> q;
void dij(int s,int t)
{
    memset(dis,0x3f,sizeof(dis));
    memset(vis,0,sizeof (vis));
    dis[s]=0;
    ty2 tmp;
    tmp.x=s,tmp.dis=0;
    q.push(tmp);

    while(q.size())
    {
        ty2 tmp=q.top();
        q.pop();
        if(vis[tmp.x])continue;
        vis[tmp.x]=1;
        for(int i=head[tmp.x];i!=-1;i=edge[i].next){
            int y=edge[i].t;
            if(dis[y]>dis[tmp.x]+edge[i].l){
                dis[y]=dis[tmp.x]+edge[i].l;
                ty2 tmp2;
                tmp2.x=y,tmp2.dis=dis[y];
                q.push(tmp2);
            }
        }
    }
    if(dis[t]>=0x3f3f3f3f)cout<< -1<<'\n';
    else
        cout<<dis[t]<<'\n';
}

int main()
{
    memset(head,-1,sizeof(head));
    cin>>n>>m>>s>>t;
    for(int i=1;i<=m;i++)
    {
        int x,y,v;
        cin>>x>>y>>v;
        add(x,y,v);
        add(y,x,v);
    }
    dij(s,t);

    return 0;
}

链式前向星
如果说邻接表是不好写但效率好,邻接矩阵是好写但效率低的话,前向星就是一个相对中庸的数据结构。前向星固然好写,但效率并不高。而在优化为链式前向星后,效率也得到了较大的提升。虽然说,世界上对链式前向星的使用并不是很广泛,但在不愿意写复杂的邻接表的情况下,链式前向星也是一个很优秀的数据结构。 ——摘自《百度百科》

#include <bits/stdc++.h>
using namespace std;

typedef pair<int,int> pii;
const int N=1010;
const int M=20010;
int head[N],e[M],ne[M],w[M];
int dis[N];
bool vis[N];
int tot;
int n,m,s,t;
int x,y,v;

void add(int x,int y,int z)
{
    e[++tot]=y;
    w[tot]=z;
    ne[tot]=head[x];
    head[x]=tot;
}

void dij(int s)
{
    priority_queue<pii> p;
    dis[s]=0;
    p.push({0,s});
    while(p.size())
    {
        int x=p.top().second;
        p.pop();
        if(vis[x]) continue;
        vis[x]=1;
        for(int i=head[x];i;i=ne[i])
        {
            int y=e[i];
            int z=w[i];
            if(dis[y]>dis[x]+z)
            {
                dis[y]=dis[x]+z;
                p.push({-dis[y],y});
            }
        }
    }
}

int main()
{
    memset(dis,0x3f,sizeof(dis));
    cin>>n>>m>>s>>t;
    for(int i=1;i<=m;i++)
    {
        cin>>x>>y>>v;
        add(x,y,v);
        add(y,x,v);
    }
    dij(s);
    if(dis[t]>=0x3f3f3f3f) cout<<-1<<endl;
    else cout<<dis[t]<<endl;

    return 0;
}

Bellman-Ford算法 (需要掌握链式前向星)
暴力做法,解决负权边,但是不能有负环

# include <iostream>
# include <cstdio>
# include <cmath>
# include <cstring>
using namespace std;
# define int long long
# define N 10005
# define M 10005
int s,t,n,m,m2;
double f[N];
struct node{
    int x,y;
}a[N];
struct node2{
    int to,next;
    double w;
}e[M];
int adj[N];
void add(int u,int v,double w2){
    m2++;
    e[m2].to=v;
    e[m2].w=w2;
    e[m2].next=adj[u];
    adj[u]=m2;
    return ;
}
void relax(int u,int v,double w2){
    if (f[v]>f[u]+w2){
        f[v]=f[u]+w2;
    }
    return ;
}
void ford(){
    memset(f,0x7f7f,sizeof(f));
    f[s]=0;
    for (int i=1;i<=n-1;i++){
        for (int j=1;j<=n;j++){
            for (int k=adj[j];k;k=e[k].next){
                int l=e[k].to;
                relax(j,l,e[k].w);
            }
        }
    }
    return ;
}
signed main(){
    ford();
    printf("%.2lf",f[t]);
    return 0;
}

SPFA(贝尔曼-福特算法的优化算法)

#include <bits/stdc++.h>
using namespace std;

typedef pair<int,int> pii;
const int N=10010;
const int M=200010;
int head[N];
int dis[N];
bool vis[N];
int tot;
int n,m,s,t;
struct ty{
    int t,l,next;
}edge[200010];

void add(int x,int y,int z){
    edge[++tot].l=z;
    edge[tot].t=y;
    edge[tot].next=head[x];
    head[x]=tot;
}
struct ty2 {
    int x, dis;
    bool operator<(const ty2 &a) const{
        return dis>a.dis;
    }
};

queue<int>q1;
void spfa(int s,int t)
{
    memset(dis,0x3f,sizeof(dis));
    memset(vis,0,sizeof (vis));
    dis[s]=0;
    vis[s]=1;
   q1.push(s);
   while(q1.size()){
       int x=q1.front();
       q1.pop();
       vis[x]=0;
       for(int i=head[x];i!=-1;i=edge[i].next){
           int y=edge[i].t;
           if(dis[y]>dis[x]+edge[i].l){
               dis[y]=dis[x]+edge[i].l;
               if(!vis[y]){
                   q1.push(y);
                   vis[y]=1;
               }
           }
       }
   }
   if(dis[t]>=0x3f3f3f3f)cout<<-1<<'\n';
   else
       cout<<dis[t]<<'\n';
}

int main()
{
    memset(head,-1,sizeof(head));
    cin>>n>>m>>s>>t;
    for(int i=1;i<=m;i++)
    {
        int x,y,v;
        cin>>x>>y>>v;
        add(x,y,v);
        add(y,x,v);
    }
    spfa(s,t);

    return 0;
}

Floyd

typedef struct          
 2 {        
 3     char vertex[VertexNum];                                //顶点表         
 4     int edges[VertexNum][VertexNum];                       //邻接矩阵,可看做边表         
 5     int n,e;                                               //图中当前的顶点数和边数         
 6 }MGraph; 
 7 
 8 void Floyd(MGraph g)
 9 {
10    int A[MAXV][MAXV];
11    int path[MAXV][MAXV];
12    int i,j,k,n=g.n;
13    for(i=0;i<n;i++)
14       for(j=0;j<n;j++)
15       {   
16              A[i][j]=g.edges[i][j];
17             path[i][j]=-1;
18        }
19    for(k=0;k<n;k++)
20    { 
21         for(i=0;i<n;i++)
22            for(j=0;j<n;j++)
23                if(A[i][j]>(A[i][k]+A[k][j]))
24                {
25                      A[i][j]=A[i][k]+A[k][j];
26                      path[i][j]=k;
27                 } 
28      } 
29 }

标签:总结,图论,int,head,tot,vis,算法,edge,dis
From: https://www.cnblogs.com/dontian/p/18344464

相关文章

  • 代码随想录算法训练营第64天 | 图论:Floyd 算法+A * 算法
    97.小明逛公园https://kamacoder.com/problempage.php?pid=1155Floyd算法精讲https://www.programmercarl.com/kamacoder/0097.小明逛公园.html#floyd-算法精讲Floyd算法精讲问题总结:双向道路;路径规划;多个起点到多个终点核心思想:动态规划确定dp数组和下标含义:grid......
  • 揭秘人工智能三大基石:数据、算法与算力的深度融合
    在科技日新月异的今天,人工智能(AI)作为引领未来科技浪潮的核心力量,正以前所未有的速度改变着我们的生活、工作乃至整个社会的面貌。人工智能的快速发展并非偶然,而是建立在三大坚实基石之上:数据、算法与计算能力。这三者相辅相成,共同构筑了人工智能技术的基石,推动了AI技术的不断突破......
  • 2024-8-7 算法学习
    P6136【模板】普通平衡树(数据加强版)题意:1,插入一个数;2,删除一个数3,查询一个数的排名4,查询第x个数5,查询x的前驱和后继重点在于分裂split和合并merge操作:1:分裂为X[0,x],Y[x+1,n],后rt=merge(X,x,Y)2:分裂为X[0,x-1],Y[x,x],Z[x+1,n]后Y=merge(Y.l,Y.r),后rt=merge(X,Y,Z);3......
  • CSP模拟 小 trick 总结 (持续施工中)
    虽然这篇博客来的有点晚,但还是写了,欢迎dalao补充(1、分块、莫队有关:(1):一个真正的回滚莫队(感谢Qyun的讲解)$\\\\\\\\$学习回滚莫队的时候,我们经常会在回滚时使用memcpy来恢复以前的版本,但众所周知--memset和memcpy常数巨大,破坏了莫队$O(n\sqrtn)$的时间复杂度,导......
  • paxos算法详解
    1分布式一致性:共识算法对于一个分布式系统来说,保障集群中所有节点的数据完全相同(即一致性)是很重要的,随着多节点的引入,这影响的是整个分布式系统对外服务的表象一致性。也就是说,一个分布式系统想要做到完全的一致性,需要对外表现为顺序一致性,即各个节点上的操作顺序都一致。而在......
  • 【Python机器学习】利用AdaBoost元算法提高分类性能——基于单层决策树构建弱分类器
    单层决策树(也称决策树桩)是一种简单的决策树。它基于单个特征来做决策,由于这棵树只有一次分裂过程,因此它实际上就是一个树桩。在构造AdaBoost代码时,首先通过一个简单数据集来确保在算法上一切就绪:fromnumpyimport*defloadSimpData():datMat=matrix([[1.0,2.1],......
  • 机器学习算法之一 线性回归
    1.线性预测函数定义左侧为真实值,右侧为预测值与误差的和,其中为权重矩阵。2.目标函数的推导2.1高斯分布函数误差符合独立同分布假设,服从均值为0的高斯分布:将线性函数带入,得:......
  • 文心一言 VS 讯飞星火 VS chatgpt (320)-- 算法导论22.3 12题
    十二、证明:我们可以在无向图G上使用深度优先搜索来获得图G的连通分量,并且深度优先森林所包含的树的棵数与G的连通分量数量相同。更准确地说,请给出如何修改深度优先搜索来让其给每个结点赋予一个介于1和k之间的整数值v.cc,这里k是G的连通分量数,使得u.cc=v.cc当且仅当结点u和结......
  • 文心一言 VS 讯飞星火 VS chatgpt (319)-- 算法导论22.3 11题
    十一、请解释有向图的一个结点u怎样才能成为深度优先树中的唯一结点,即使结点u同时有入边和出边。如果要写代码,请用go语言。文心一言:在一个有向图中,如果结点u在深度优先搜索(DFS)的过程中成为深度优先树(DFS树)中的唯一结点,这通常意呀着在DFS遍历的某个特定时刻,从u出发能够探索......
  • 清晰易懂二分查找算法 你确定不看吗?
    @目录前言简介一、二分查找算法的原理是什么?1.确定搜索范围:2.计算中间位置:3.比较中间元素:4.调整搜索范围:5.重复迭代:二、二分查找算法的优缺点是什么?优点:缺点:三、java实现二分查找案例总结前言请各大网友尊重本人原创知识分享,谨记本人博客:南国以南i、提示:以下是本篇文......