题目地址:http://sdau.openjudge.cn/graph/
 
dijkstra求最短路径
#include <bits/stdc++.h>
using namespace std;
#define ll long long 
const int N=200005;
int n,m,st,en;
bool vis[N];//标记数组
ll dist[N];//距离数组
int pre[N];//前驱
int head[N],tot;
//结构体数组edge存边,edge[i]表示第i条边,
//head[i]存以i为起点的第一条边(在edge中的下标)
struct node
{
    int next; //下一条边的存储下标
    int to; //这条边的终点
    ll w;//权值
} edge[N*4];
///tot为边的计数,从0开始计,每次新加的边作为第一条边,最后倒序遍历
void add(int u,int v,ll w)
{
    edge[tot].to=v;
    edge[tot].w=w;
    edge[tot].next=head[u];
    head[u]=tot++;
}
void init()
{
    tot=0;
    memset(head,-1,sizeof(head));
    memset(pre,-1,sizeof(pre));
}
struct Rec
{
    int id; //节点编号
    ll dis; //距离
    /*bool operator<(const Rec &tmp)const{
        return dis>tmp.dis;
    }  */
};
bool operator <(const Rec&a,const Rec&b)
{
    return a.dis>b.dis;
}  
priority_queue<Rec> q;//重载小于号实现小根堆
void dijkstra()
{
    for(int i=0; i<=n; i++)
        dist[i]=1e18;
    memset(vis,0,sizeof(vis));
    
    dist[st]=0;
    Rec rec;rec.id=st;rec.dis=0;
    q.push(rec);
    while(!q.empty())
    {
        int u=q.top().id;
      
        q.pop();
        if(vis[u])
            continue;
        vis[u]=1;
        for(int i=head[u]; i!=-1; i=edge[i].next) //遍历以u为起点的所有边,与输入顺序相反
        {
            int v=edge[i].to;
            ll w=edge[i].w;
            if(dist[v]>dist[u]+w)
            {
                dist[v]=dist[u]+w;
                Rec rec;
                rec.id=v;
                rec.dis=dist[v];
                q.push(rec);
                pre[v]=u;
            }
        }
    }
}
vector<int> path;
void  getPath()
{
    for(int i=en; i!=-1; i=pre[i])
    {
        path.push_back(i);
    }
}
int main()
{
    scanf("%d%d",&n,&m);  
    st=1;en=n;
    scanf("%d%d",&st,&en); 
    int u,v;
    ll w;
    init();
    for(int i=1; i<=m; i++)
    {
        scanf("%d%d%lld",&u,&v,&w);
        add(u,v,w);
    }
    dijkstra();
    if(dist[en]==1e18)
    {
        cout<<"no answer"<<endl;
    }
    else
    {
        cout<<dist[en]<<endl;
        getPath();
        for(int i=path.size()-1;i>=0;i--)
        {
            cout<<"v"<<path[i]<<" ";
        }
        cout<<endl;
    }
    return 0;
}
floyd求最短路径
 
#include <bits/stdc++.h>
using namespace std;
const int N=1000;
int n,m;
int dist[N][N];
vector<int> path[N][N];
int main()
{
     scanf("%d%d",&n,&m);
     for(int i=0;i<n;i++)
        for(int j=0;j<n;j++)
        dist[i][j]=1e9;
     for(int i=1;i<=m;i++)
     {
        int u,v,w;
        scanf("%d%d%d",&u,&v,&w);
        dist[u][v]=w;
        path[u][v].push_back(u);
        path[u][v].push_back(v);
     }
     for(int k=0;k<n;k++)
        for(int i=0;i<n;i++)
         for(int j=0;j<n;j++)
     {
        if(dist[i][j]>dist[i][k]+dist[k][j])
        {
            dist[i][j]=dist[i][k]+dist[k][j];
            path[i][j].clear();
            for(int t=0;t<path[i][k].size()-1;t++)
                path[i][j].push_back(path[i][k][t]);
                
            for(int t=0;t<path[k][j].size();t++)
                path[i][j].push_back(path[k][j][t]);
            
        }
     }
     int flag=0;
     for(int i=0;i<n;i++)
     {
        for(int j=0;j<n;j++)
            {
                if(i==j) continue;
                cout<<dist[i][j]<<" ";
                for(int t=0;t<path[i][j].size();t++)
                cout<<"v"<<path[i][j][t]<<" ";
                cout<<endl;
                flag=1;
            }
     }
     if(flag==0) cout<<"no answer"<<endl;
    return 0;
}
求关键路径
#include <bits/stdc++.h>
using namespace std;
const int N=1000;
int head[N],tot;
int ve[N],vl[N],ee[N],el[N];
//ve[i]:顶点i最早开始的时间,vl[i]:顶点i最晚开始的时间
//et[i]:边i最早开始的时间,  el[i]:边i最晚开始的时间
stack<int> s;//保存反向拓扑的序列
queue<int> ans_q;
struct node
{
    int to;
    int next;
    int w;
}edge[N*2];
void add(int u,int v,int w)
{
    edge[tot].to=v;
    edge[tot].w=w;
    edge[tot].next=head[u];
    head[u]=tot++;
}
int n,m;
int in[N],out[N];
int topo() //求出点的最早发生时间
{
    priority_queue<int,vector<int>,greater<int> > q;
    for(int i=1;i<=n;i++)
    {  
       if(in[i]==0)
        q.push(i);  
    }
    while(!q.empty())
    {
        int u=q.top();
        s.push(u);
        
        q.pop();
        for(int i=head[u];i!=-1;i=edge[i].next)
        {
            int v=edge[i].to;
            in[v]--;
            if(in[v]==0)
                q.push(v);
            
            if(ve[v]<ve[u]+edge[i].w)
            {
               ve[v]=ve[u]+edge[i].w;
            }
        }
    }
    /*for(int i=1;i<=n;i++)
    {
        cout<<ve[i]<<" ";
    }
    cout<<endl; */
}
int ReverseTopo()
{
    memset(vl,127,sizeof(vl));
     
    for(int i=1;i<=n;i++)
    {
        if(out[i]==0)
        {
            vl[i]=ve[i];
        }
    }
    
    while(!s.empty())
    {
        int u=s.top();
        s.pop();
        for(int i=head[u];i!=-1;i=edge[i].next)
        {
            int v=edge[i].to;
            if(vl[u]>vl[v]-edge[i].w)
            {
                vl[u]=vl[v]-edge[i].w;
            }
        }
    }
    /*for(int i=1;i<=n;i++)
    {
        cout<<vl[i]<<" ";
    }
    cout<<endl; */
}
vector<int>ans;
int main()
{
    tot=0;
    memset(head,-1,sizeof(head));
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++)
    {
        int u,v,w;
        scanf("%d%d%d",&u,&v,&w);
        add(u,v,w);
        in[v]++;
        out[u]++;
    }
    topo();
    ReverseTopo();
    int endd;
    for(int u=1;u<=n;u++)
    {
         for(int i=head[u];i!=-1;i=edge[i].next)
         {
            int v=edge[i].to;
            int w=edge[i].w;
            ee[u]=ve[u];//边最早发生的时间
            el[u]=vl[v]-w;边最晚发生的时间
            if(ee[u]==el[u])
            {
                ans.push_back(u);
                endd=v;
            }
         }
    }
    for(int i=0;i<ans.size();i++)
    {
        cout<<"v"<<ans[i]<<" ";
    }    
    cout<<"v"<<endd;
    return 0;
}
拓扑排序
#include <bits/stdc++.h>
using namespace std;
const int N=1000;
int head[N],tot;
struct node
{
    int to;
    int next;
    int w;
}edge[N*2];
void add(int u,int v)
{
    edge[tot].to=v;
    edge[tot].next=head[u];
    head[u]=tot++;
}
int n,m;
int in[N];
int topo()
{
    priority_queue<int,vector<int>,greater<int> > q;
    for(int i=1;i<=n;i++)
    {  
       if(in[i]==0)
        q.push(i);  
    }
    while(!q.empty())
    {
        int u=q.top();
        q.pop();
        cout<<"v"<<u<<" ";
        for(int i=head[u];i!=-1;i=edge[i].next)
        {
            int v=edge[i].to;
            in[v]--;
            if(in[v]==0)
                q.push(v);
        }
    }
}
int main()
{
    tot=0;
    memset(head,-1,sizeof(head));
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++)
    {
        int u,v;
        scanf("%d%d",&u,&v);
        add(u,v);
        in[v]++;
    }
    topo();
    return 0;
}
kruskal算法求最小生成树
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int N=1000;
int head[N],tot,fa[N];
int n,m;
struct node
{
    int from;
    int to;
    int next;
    ll  w;
} edge[N*N];
bool operator<(node a,node b)
{
    return a.w<b.w;
}
void add(int u,int v,ll w)
{
    edge[tot].from=u;
    edge[tot].to=v;
    edge[tot].w=w;
    edge[tot].next=head[u];
    head[u]=tot++;
}
int get(int x)
{
    if(x==fa[x])
        return x;
    else
        return fa[x]=get(fa[x]);
}
bool cmp(node x,node y)
{
     if(x.from==y.from)
        return x.to<y.to;
     else
        return x.from<y.from;
}
ll a[N][N];
vector<node> ans;
int main()
{
    tot=0;
    memset(head,-1,sizeof(head));
    for(int i=0; i<N; i++)
    {
        fa[i]=i;
    }
    scanf("%d%d",&n,&m);
    for(int i=1; i<=n; i++)
        for(int j=1; j<=n; j++)
        {
            scanf("%lld",&a[i][j]);
        }
    for(int i=1; i<=n; i++)
        for(int j=i+1; j<=n; j++)
        {
            if(a[i][j]==100)
                continue;
            if(i==j)
                continue;
            add(i,j,a[i][j]);
        }
    sort(edge,edge+m);
    int cnt=0;
    for(int i=0; i<m; i++)
    {
        int fu=get(edge[i].from);
        int fv=get(edge[i].to);
        if(fu!=fv)
        {
            node temp;
            temp.from=edge[i].from;
            temp.to=edge[i].to;
            ans.push_back(temp);
            fa[fu]=fv;
            cnt++;
            if(cnt==n-1)
                break;
        }
    }
    //sort(ans.begin(),ans.end(),cmp);
    for(int i=0;i<cnt;i++)
    {
    cout<<ans[i].from<<" "<<ans[i].to<<" ";
    }
    return 0;
}
prim算法求最小生成树
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int N=1000;
int n,m;
int a[N][N];
vector<int> ans;
int d[N],vis[N];
void prim()
{
    memset(d,127,sizeof(d));
    memset(vis,0,sizeof(vis));
    d[1]=0;
    int pre=1;
    for(int i=1;i<=n;i++)
    {
        int x=0;
        for(int j=1;j<=n;j++)
        {
            if(vis[j]==0&&(x==0||d[j]<d[x])) 
            {
                x=j;
                
            }
        }
        vis[x]=1;
        int temp=x;
        for(int y=1;y<=n;y++)
        {
            if(vis[y]==0)
            {
                if(d[y]>a[x][y])
                {
                    d[y]=a[x][y];
                }
            }
        }
        ans.push_back(d[x]);
        pre=x;
    }
}
int main()
{
    scanf("%d%d",&n,&m);
    memset(a,127,sizeof(a));
    for(int i=1; i<=n; i++)
        for(int j=1; j<=n; j++)
        {
            if(a[i][i]==100)continue;
            scanf("%d",&a[i][j]);
        }
    prim();
    for(int i=1;i<n;i++)
    {
    cout<<ans[i]<<" ";
    }
    return 0;
}