• [模板] 最短路/差分约束


    最短路

    SPFA

    时间复杂度 (O(nm)), 空间复杂度 (O(n)).

    STL队列.

    ll dis[nsz];
    int vi[nsz],cnt[nsz];
    queue<int> qu;
    bool spfa(int s)
    {
    	rep(i,1,n)vi[i]=0,dis[i]=ninf;
    	qu.push(s),dis[s]=0,vi[s]=1;
    	int u;
    	while(!qu.empty()){
    		u=qu.front(),qu.pop(),vi[u]=0;
    		forg(u,i,v){
    			if(dis[v]>dis[u]+edge[i].v){
    				dis[v]=dis[u]+edge[i].v;
    				cnt[v]=cnt[u]+1;
    				if(cnt[v]>=n)return 0; //no solution
    				if(vi[v]==0){
    					qu.push(v),vi[v]=1;
    				}
    			}
    		}
    	}
    	return 1;
    }
    

    手写队列.

    亲测比STL慢, 似乎大量的时间浪费在取模上...==

    //graph
    const int nsz=1e4+50,msz=500050;
    ll ninf=1e17;
    int n,m,s;
    
    struct te{int t,v,pr;}edge[msz<<1];
    int hd[nsz],pe=1;
    void adde(int f,int t,int v){edge[++pe]=(te){t,v,hd[f]};hd[f]=pe;}
    #define forg(p,i,v) for(int i=hd[p],v=edge[i].t;i;i=edge[i].pr,v=edge[i].t)
    
    //spfa
    ll dis[nsz];
    int vi[nsz],cnt[nsz];
    int que[nsz],qh=1,qt=0;
    int qfront(){return que[qh%n];}
    void qpush(int v){que[(++qt)%n]=v;}
    bool spfa(int s)
    {
    	rep(i,1,n)vi[i]=0,dis[i]=ninf;
    	qpush(s),dis[s]=0,vi[s]=1;
    	int u;
    	while(qh<=qt){
    		u=qfront(),++qh,vi[u]=0;
    		forg(u,i,v){
    			if(dis[v]>dis[u]+edge[i].v){
    				dis[v]=dis[u]+edge[i].v;
    				cnt[v]=cnt[u]+1;
    				if(cnt[v]>=n)return 0;
    				if(vi[v]==0){
    					qpush(v),vi[v]=1;
    				}
    			}
    		}
    	}
    	return 1;
    }
    

    Dijkstra

    时间复杂度 (O((n+m)log n)).

    ll dis[nsz];
    int vi[nsz];
    struct tdis{int x;ll d;};
    bool operator<(tdis l,tdis r){return l.d>r.d;}
    void dij(){
        priority_queue<tdis> pq;
        rep(i,1,n)dis[i]=ninf,vi[i]=0;
        dis[s]=0;
        pq.push((tdis){s,0});
        while(!pq.empty()){
            int u=pq.top().x;pq.pop();
            if(vi[u])continue;
            vi[u]=1;
            for(int i=h[u],v=edge[i].t;i;i=edge[i].pr,v=edge[i].t){
                if(dis[v]>dis[u]+edge[i].d){
                    dis[v]=dis[u]+edge[i].d;
                    pq.push((tdis){v,dis[v]});
                }
            }
        }
    }
    

    差分约束

    对于 (x_i - x_j le a_i), 它等价于三角不等式 (x_i le x_j + a_i).

    建有向边 ((x_j, x_i)), 边权 (a_i). 跑最长路即可. 也可以边权 (-a_i), 跑最短路.

    当跑最长路时, spfa无解的充要条件是图中存在正环, 这也等价于不等式组无解.

    对于其他类似的不等式, 可以转化为上述形状.

  • 相关阅读:
    Java的HashMap
    为什么 char c = 'A';c += 32; 结果输出的是 'a'?
    java中整数的常量优化机制
    IDEA2019版中文汉化包
    asp.net项目协作开发时,常常要忽略版本控制的目录
    SQLServer同步数据到ElasticSearch
    为什么不建议在微信小程序的TarBar上检查统一登录后跳转页面
    nginx的热备方式
    HTTP 和FTP 状态信息总结(留着自己用)
    Web Api 简介
  • 原文地址:https://www.cnblogs.com/ubospica/p/10427648.html
Copyright © 2020-2023  润新知