算法板子--图

dijkstra算法

算法笔记版

const int inf = 1e9;
const int maxn = 1005;
int g[maxn][maxn];
int d[maxn];
bool vi[maxn];
vector<int> pre[maxn];
int n;

void dj(int s) {
	fill(d, d + maxn, inf);
	d[s] = 0;
	for (int i = 0; i < n; i++) {
		int u = -1, minn = inf;
		for (int j = 0; j < n; j++) {
			if (vi[j] == false && d[j] < minn) {
				u = j;
				minn = d[j];
			}
		}
		if (u == -1)return;
		vi[u] = true;
		for (int v = 0; v < n; v++) {
			if (!vi[v] && g[u][v] != inf) {
				if (d[u] + g[u][v] < d[v]) {
					d[v] = d[u] + g[u][v];
					pre[v].clear();
					pre[v].push_back(u);
				}
				else if (d[u] + g[u][v] == d[v]) {
					pre[v].push_back(u);
				}
			}
		}
	}
}

y总版

#include<iostream>
#include<cstring>
#include<algorithm>

using namespace std;

const int inf=0x3f3f3f3f;
const int N=510;
int g[N][N];
bool vi[N];
int d[N];
int n,m;


void dj(){
    memset(d, 0x3f,sizeof d);
    d[1]=0;

    for(int i=1;i<=n;i++){
        int u=-1,minn=inf;
        for(int j=1;j<=n;j++ ){
            if(!vi[j] && (u==-1 || d[j]<d[u])){
                minn=d[j];
                u=j;
            }
        }
        if(u==-1)return ;
        vi[u]=true;
        
        for (int j = 1; j <= n; ++j) {
            d[j] = min(d[j], d[u] + g[u][j]);
        }
    }
}

int main(){
    cin>>n>>m;
    memset(g, 0x3f, sizeof g);
    
    for(int i=1;i<=m;i++){
        int a,b,c;
        cin>>a>>b>>c;
        g[a][b]=min(g[a][b],c);
    }    
    
    dj();
    
    if(d[n]==inf)cout<<"-1";
    else cout<<d[n];
    return 0;
}

堆优化dijkstra

朴素、堆优化dijkstra详解

#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;

const int inf=0x3f3f3f3f;
const int N=1e6;
int n,m;
int h[N],w[N],e[N],ne[N],idx;
int d[N];
bool vi[N];
typedef  pair<int,int> PII;

void add(int a,int b,int c){
    e[idx]=b;
    w[idx]=c;
    ne[idx]=h[a];
    h[a]=idx++;
}

void dj(){
    memset(d,0x3f, sizeof d);
    d[1]=0;
    priority_queue<PII,vector<PII>,greater<PII> > q;
    q.push({0,1});
    
    while(q.size()){
        auto t=q.top();
        q.pop();
        
        int u=t.second;
        
        if(vi[u])continue;
        vi[u]=true;
        
        for(int i=h[u];~i;i=ne[i]){
            int v=e[i];
            if(d[v]>d[u]+w[i]){
                d[v]=d[u]+w[i];
                q.push({d[v],v});
            }
        }
    }
}
int main(){
    memset(h, -1, sizeof h);
    
    cin>>n>>m;
    for(int i=1;i<=m;i++){
        int a,b,c;
        cin>>a>>b>>c;
        add(a,b,c);
    }
    
    dj();
    
    if(d[n]==inf) cout<<"-1";
    else cout<<d[n]<<endl;

    return 0;
}

bellman-ford算法

int n, m;       // n表示点数,m表示边数
int dist[N];        // dist[x]存储1到x的最短路距离

struct Edge     // 边,a表示出点,b表示入点,w表示边的权重
{
    int a, b, w;
}edges[M];

// 求1到n的最短路距离,如果无法从1走到n,则返回-1。
int bellman_ford()
{
    memset(dist, 0x3f, sizeof dist);
    dist[1] = 0;

    // 如果第n次迭代仍然会松弛三角不等式,就说明存在一条长度是n+1的最短路径,由抽屉原理,路径中至少存在两个相同的点,说明图中存在负权回路。
    for (int i = 0; i < n; i ++ )
    {
        for (int j = 0; j < m; j ++ )
        {
            int a = edges[j].a, b = edges[j].b, w = edges[j].w;
            if (dist[b] > dist[a] + w)
                dist[b] = dist[a] + w;
        }
    }

    if (dist[n] > 0x3f3f3f3f / 2) return -1;
    return dist[n];
}

spfa算法(求最短路,不能有负环)

链表前向星版

#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;

const int N=1e5+10;
const int inf=0x3f3f3f3f;
int n,m;
int h[N],e[N],w[N],ne[N],idx;
bool st[N];
int d[N];

void add(int a,int b,int c){
    e[idx]=b;
    w[idx]=c;
    ne[idx]=h[a];
    h[a]=idx++;

}

void spfa(){
    memset(d, 0x3f, sizeof d);
    d[1]=0;

    queue<int> q;
    q.push(1);
    st[1]=true;

    while(q.size()){
        auto u=q.front();
        q.pop();

        st[u]=false;
        for(int i=h[u];~i;i=ne[i]){
            int v=e[i];
            if(d[v]>d[u]+w[i]){
                d[v]=d[u]+w[i];
                if(!st[v]){
                    q.push(v);
                    st[v]=true;
                }
            }
        }
    }

}
int main(){
    memset(h,-1,sizeof h);
    cin>>n>>m;
    for(int i=1;i<=m;i++){
        int a,b,c;
        cin>>a>>b>>c;
        add(a,b,c);
    }

    spfa();

    if(d[n]==inf)cout<<"impossible";
    else cout<<d[n];
    return 0;
}

stl版

struct node{
    int v;
    int dis;
};
const int N=1e5+10;
const int inf=0x3f3f3f3f;
int n,m;
int d[N];
vector<node> g[N];
bool st[N];

//返回点s到点ed的距离,若res==inf,则不可达
int spfa(int s,int ed){
    memset(d,0x3f,sizeof d);
    d[s]=0;
    
    queue<int> q;
    q.push(s);
    st[s]=true;
    
    while(q.size()){
        int t=q.front();
        q.pop();
        st[t]=false;
        for(int i=0;i<g[t].size();i++){
            int v=g[t][i].v;
            int dis=g[t][i].dis;
            if(d[v]>d[t]+dis){
                d[v]=d[t]+dis;
                if(!st[v]){
                    q.push(v);
                    st[v]=true;
                }
            }
            
        }
    }
    
    return d[ed];
}

spfa(求是否有负环)

链表前向星版

#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;

const int N=1e5+10;
const int inf=0x3f3f3f3f;
int n,m;
int h[N],e[N],w[N],ne[N],idx;
bool st[N];
int d[N],cnt[N];

void add(int a,int b,int c){
    e[idx]=b;
    w[idx]=c;
    ne[idx]=h[a];
    h[a]=idx++;
}

bool spfa(){
    queue<int> q;
    for(int i=1;i<=n;i++){
        q.push(i);
        st[i]=true;
    }
    
    while(q.size()){
        auto u=q.front();
        q.pop();
        
        st[u]=false;
        for(int i=h[u];~i;i=ne[i]){
            int v=e[i];
            if(d[v]>d[u]+w[i]){
                d[v]=d[u]+w[i];
                cnt[v]=cnt[u]+1;
                if(cnt[v]>=n)return true;
                if(!st[v]){
                    q.push(v);
                    st[v]=true;
                }
            }
        }
    }
    return false;
}
int main(){
    memset(h,-1,sizeof h);
    cin>>n>>m;
    for(int i=1;i<=m;i++){
        int a,b,c;
        cin>>a>>b>>c;
        add(a,b,c);
    }
    
    spfa();
    
    if(spfa())cout<<"Yes";
    else cout<<"No";
    return 0;
}

stl版

#include<iostream>
#include<queue>
#include<vector>
#include<cstring>
using namespace std;

struct node{
    int y;
    int w;
};
const int inf=0x3f3f3f3f;
const int N=2010;
int n,m;
vector<node>g[N];
int d[N],cnt[N];
bool st[N];

bool spfa(){

    queue<int > q;
    for(int i=1;i<=n;i++){
        st[i]=true;
        q.push(i);
    }
    
    while(q.size()){
        int t=q.front();
        q.pop();
        st[t]=false;
        for(int i=0;i<g[t].size();i++){
            int v=g[t][i].y;
            int dis=g[t][i].w;
            if(d[v]>d[t]+dis){
                cnt[v]=cnt[t]+1;
                if(cnt[v]>=n)return true;//有负环
                d[v]=d[t]+dis;
                if(!st[v]){
                    st[v]=true;
                    q.push(v);
                }
            }
        }
    }
    return false;
}

int main(){
    cin>>n>>m;
    for(int i=0;i<m;i++){
        int a,b,c;
        cin>>a>>b>>c;
        g[a].push_back({b,c});
        
    }
    bool res=spfa();
    if(res==true) cout<<"Yes";
    else cout<<"No";
    return 0;
}

拓扑排序

const int maxn=1e5+10;
int n,m;
vector<int> g[maxn];
int d[maxn];
vector<int> res;//存储拓扑排序序列

bool topsort(){
    queue<int> q;
    int num=0;
    for(int i=1;i<=n;i++){
        if(d[i]==0) q.push(i);
    }
    
    while(!q.empty()){
        int u=q.front();
        q.pop();
        num++;
        res.push_back(u);
        for(int i=0;i<g[u].size();i++){
            int v=g[u][i];
            if(--d[v]==0) q.push(v);
        }
    }
    if(num==n) return true;
    else return false;
    
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值