My Title

最短路模板

呃最短路要最好需要掌握的三种算法:dijkstra、SPFA、floyd;

区别在于:

·dijkstra最好用于稠密图;

·SPFA最好用于稀疏图;

·floyd可以用来写闭包(huaji)

·其他区别因为太菜暂时不列出来

 

先上个spfa模板:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
#include<set>
using namespace std;
#define REG register
#define REP(i,x,y) for(register int i=x;i<=y;i++)
#define UP(i,x,y) for(register int i=x;i>=y;i--)
#define IN inline
#define inf 0x3f3f3f3f

const int maxn=2505,maxm=6205;
int dis[maxn]={0},head[maxm*2]={0},tot=0,n,m,ts,te;
bool vis[maxn]={0};
struct edge{
    int next,to,w;
}h[maxm*2];
queue <int> Q;

IN void add(int u,int v,int w){
    h[++tot].next=head[u],h[tot].to=v,h[tot].w=w,head[u]=tot;
}

IN void SPFA(){
    REP(i,1,n) dis[i]=inf;
    int u,v;
    Q.push(ts);
    dis[ts]=0;vis[ts]=1;
    while(!Q.empty()){
        int u=Q.front();Q.pop();
        vis[u]=0;
        for(REG int i=head[u];i;i=h[i].next){
            v=h[i].to;
            if(dis[v]>dis[u]+h[i].w){
                dis[v]=dis[u]+h[i].w;
            if(!vis[v]){
                vis[v]=1;Q.push(v);
            }
            }
        }
    }
}

int main(){
    scanf("%d %d %d %d",&n,&m,&ts,&te);
    REP(i,1,m){
        int x,y,z;
        scanf("%d %d %d",&x,&y,&z);
        add(x,y,z);add(y,x,z);
    }
    SPFA();
    printf("%d",dis[te]);
    
    return 0;
}
View Code

·负环:进队次数>n就有负环;或开数组记录步数(最短路路径条数),步数>n即有负环。

IN void spfa(int s){
    if(flag) return; vis[s]=1; 
    for(int i=head[s];i;i=e[i].ne){
        if(flag) return; 
        int to=e[i].to;
        if(d[to]>d[s]+e[i].va){
            d[to]=d[s]+e[i].va;
            if(vis[to]){flag=1;return;}
            else spfa(to);
        }
    }
    vis[s]=0;
}
View Code

 

再来个dijkstra模板(堆优化):

(因现在水平真心菜,等更好理解重新不丑的)

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
#include<set>
using namespace std;
#define REG register
#define REP(i,x,y) for(register int i=x;i<=y;i++)
#define UP(i,x,y) for(register int i=x;i>=y;i--)
#define IN inline
#define inf 0x7fffffff

struct node
{
    int to,dis;
    bool operator <(const node &t) const
    {
        return dis>t.dis;
    }
};

int n,m,s;
bool visit[10050];
int dis[500050];
vector <node> g[10050];
priority_queue <node> q;

int main()
{
    scanf("%d%d%d",&n,&m,&s);
    for (int i=1;i<=m;i++)
        dis[i]=inf;
    for (int i=1;i<=m;i++)
    {
        int u,v,d;
        scanf("%d%d%d",&u,&v,&d);
        g[u].push_back((node){v,d});
    }
    dis[s]=0;
    q.push((node){s,0});
    while (!q.empty())
    {
        node p=q.top();
        q.pop();
        int x=p.to;
        if (visit[x])
            continue;
        visit[x]=1;
        for (int i=0;i<g[x].size();i++)
        {
            node np=g[x][i];
            int x1=np.to;
            if (dis[x1]>dis[x]+np.dis)
            {
                dis[x1]=dis[x]+np.dis;
                q.push((node){x1,dis[x1]});
            }
        }
    }
    for (int i=1;i<=n;i++)
        printf("%d ",dis[i]);
    printf("\n");
    
    return 0;
}
View Code

 

然后就是floyd,这个真心不会,只能来个裸的三循环:

    REP(k,1,n)
        REP(i,1,n)
            REP(j,1,n)
                d[i][j]=min(d[i][j],d[i][k]+d[k][j]);

 

 接着来个差分约束系统:

先来个 两边夹定理:A-B=C  <=>  A-B>=C&&A-B<=C,

还有著名的三角形不等式;

 

 应用:

1、线性约束:

   对于所有满足d[x] - d[y] <= z的不等式,从y向x建立一条权值为z的有向边。
   然后从起点1出发,利用SPFA求到各个点的最短路,如果1到N不可达,说明最短路(即上文中的T)无限长,输出-2。如果某个点进入队列大于等于N次,则必定存在一条负环,即没有最短路,输出-1。否则T就等于1到N的最短路。

2、区间约束;

3、未知条件约束:指在不等式的右边不一定是个常数,可能是个未知数,可以通过枚举这个未知数,然后对不等式转化成差分约束进行求解

 

注意;

1、可以开二维来进行其它的判断(例如 颜色不同的路才能走)

 

 

(待完善)

posted @ 2018-03-16 23:00  EvfX  阅读(277)  评论(0编辑  收藏  举报