图算法补充(SPFA,最长路径)

1. SPFA(Shortest Path Faster Algorithm)
1994年,西南交通大学的段凡丁发表了SPFA,SPFA在Bellman-Ford算法的基础上加上一个队列优化,减少了冗余的松弛操作。

关于最短路径的SPFA快速算法(段凡丁):http://www.cnki.com.cn/Article/CJFDTotal-XNJT402.015.htm

wiki:https://en.wikipedia.org/wiki/Shortest_Path_Faster_Algorithm

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

struct Node
{
    int v,w;
    Node *next;
    Node(int x,int y):v(x),w(y),next(0){} 
};

struct Graph
{
    int VNum,ENum;
    vector<Node *> Adj;
};

void createGraph(Graph &G)
{
    cin>>G.VNum>>G.ENum;
    for(int i=0;i<G.VNum;++i)G.Adj.push_back(0);
    for(int i=0;i<G.ENum;++i)
    {
        int u,v,w;
        cin>>u>>v>>w;
        Node *p=new Node(v,w);
        p->next=G.Adj[u];
        G.Adj[u]=p;
    }
}

vector<int> SPFA(Graph G,int s)
{
    vector<int> d(G.VNum,INT_MAX);
    vector<bool> flag(G.VNum,false);
    d[s]=0;
    queue<int> Q;
    Q.push(s);
    flag[s]=true;
    while(!Q.empty())
    {
        int u=Q.front();
        Q.pop();
        flag[u]=false;
        for(Node *p=G.Adj[u];p;p=p->next)
        {
            int v=p->v,w=p->w;
            if(d[u]+w<d[v])
            {
                d[v]=d[u]+w;
                if(!flag[v])
                {
                    Q.push(v);
                    flag[v]=true;
                }
            }
        }
    }
    return d;
}

//输入  
//5 10  
//0 1 10  
//0 3 5  
//1 2 1  
//1 3 2  
//2 4 4  
//3 1 3  
//3 2 9  
//3 4 2  
//4 0 7  
//4 2 6  
//  
//输出  
//0 8 9 5 7

int main()
{
    Graph G;
    createGraph(G);
    int s=0;
    vector<int> d=SPFA(G,s);
    for(int i=0;i<d.size();++i)cout<<d[i]<<' ';
    cout<<endl;
    return 0;
}

2. 图的最长路径
(1)Bellman-Ford算法、Floyd-Warshall算法:将图中边的权重变为原来的相反数
(2)DAG(Directed Acyclic Graph,有向无环图):拓扑排序+动态规划

AOV(Activity On Vertex)网
AOE(Activity On Edge)网的关键路径

e(i) 表示活动 ai 的最早开始时间, l(i) 表示活动 ai 的最晚开始时间。
ve(i) 表示事件 vi 的最早发生时间, vl(i) 表示事件 vi 的最晚发生时间。

uai=wve(i)=ve(u)l(i)=vl(v)wve[0]=0ve[v]=max(u,v)E{ve[u]+w},v=1,2,,n1vl[n1]=ve[n1]vl[u]=min(u,v)E{vl[v]w},u=n2,n1,,0

#include<iostream>
#include<vector>
#include<stack>
using namespace std;

struct Node
{
    int v,w;
    Node *next;
    Node(int x,int y):v(x),w(y),next(0){}
};

struct Graph
{
    int VNum,ENum;
    vector<Node *> Adj;
};

void createGraph(Graph &G)
{
    cin>>G.VNum>>G.ENum;
    for(int i=0;i<G.VNum;++i)G.Adj.push_back(0);
    for(int i=0;i<G.ENum;++i)
    {
        int u,v,w;
        cin>>u>>v>>w;
        Node *p=new Node(v,w);
        p->next=G.Adj[u];
        G.Adj[u]=p;
    }
}

vector<int> GetInDegree(Graph G)
{
    vector<int> indegree(G.VNum,0);
    for(int u=0;u<G.VNum;++u)
    {
        for(Node *p=G.Adj[u];p;p=p->next)
        {
            int v=p->v;
            ++indegree[v];
        }
    }
    return indegree;
}

void TopoSort(Graph G,stack<int> &T,vector<int> &ve)
{
    vector<int> indegree=GetInDegree(G);
    stack<int> S;
    for(int u=0;u<G.VNum;++u)
    {
        if(indegree[u]==0)S.push(u);
    }
    while(!S.empty())
    {
        int u=S.top();
        S.pop();
        T.push(u);
        for(Node *p=G.Adj[u];p;p=p->next)
        {
            int v=p->v,w=p->w;
            if(--indegree[v]==0)S.push(v);
            if(ve[u]+w>ve[v])ve[v]=ve[u]+w;
        }
    }
}

void CriticalPath(Graph G)
{
    stack<int> T;
    vector<int> ve(G.VNum,0);
    TopoSort(G,T,ve);
    vector<int> vl(G.VNum,ve[G.VNum-1]);
    while(!T.empty())
    {
        int u=T.top();
        T.pop();
        for(Node *p=G.Adj[u];p;p=p->next)
        {
            int v=p->v,w=p->w;
            if(vl[v]-w<vl[u])vl[u]=vl[v]-w;
        }
    }
    for(int u=0;u<G.VNum;++u)
    {
        for(Node *p=G.Adj[u];p;p=p->next)
        {
            int v=p->v,w=p->w;
            int ee=ve[u];
            int el=vl[v]-w;
            char tag=(ee==el)?'*':' ';
            cout<<u<<"->"<<v<<' '<<w<<' '<<ee<<' '<<el<<' '<<tag<<endl;
        }
    }
}

//6 8
//0 1 3
//0 2 2
//1 3 2
//1 4 3
//2 3 4
//2 5 3
//3 5 2
//4 5 1
int main()
{
    Graph G;
    createGraph(G);
    CriticalPath(G);
    return 0;
}
  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值