板子板子板子

排序

快速排序

void qs(int a[],int l,int r){
    if(l>=r)return;
    int i=l-1,j=r+1,x=a[l+r>>1];
    while(i<j){
        do i++;while(a[i]<x);
        do j--;while(a[j]>x);
        if(i<j)swap(a[i],a[j]);
    }  
    qs(a,l,j);
    qs(a,j+1,r);
}

归并排序

void merge_sort(int a[],int l,int r){
    if(l>=r)return;
    int mid=l+r>>1;
    merge_sort(a,l,mid);
    merge_sort(a,mid+1,r);
    
    int idx=l;
    int i=l,j=mid+1;
    while(i<=mid && j<=r){
        if(a[i]>a[j])temp[idx++]=a[j++];
        else temp[idx++]=a[i++];
    }
    while(i<=mid){
        temp[idx++]=a[i++];
    }
    
    while(j<=r){
        temp[idx++]=a[j++];
    }
    
    for(int k=l;k<=r;k++)
        a[k]=temp[k];
}

单调性算法

二分
整数二分
    int l=0,r=100;
    while(l<r){
        int mid=l+r+1>>1;
        check(mid)?l=mid:r=mid-1;
    }
    cout<<l;
浮点二分

esp要比保留小数多1位,比如保留3位小数,esp选择1e-4,精度在不出现精度问题的前提下越高越好(举例)。

const double esp=1e-4;
double l=0,r=1000;
while(r-l>esp){
    double mid=(l+r)/2;
    check(mid)?l=mid:r=mid;
}
单调栈
	for(int i=n;i>=1;i--){// 1.
	    while(t && r[st[t]]<=r[i])t--;// 2.
	    res[i]=st[t];// 3.
	    st[++t]=i;// 4.
	}
滑动窗口
    //getmax
    for(int i=1;i<=n;i++){
        int j=i-k+1;
        if(h<=t && q[h]<j)h++;
        while(h<=t && a[i]<=a[q[t]])t--;
        q[++t]=i;
        if(j>=1)cout<<a[q[h]]<<" ";
    }
    puts("");
    h=0,t=-1;
    
    //getmin
    for(int i=1;i<=n;i++){
        int j=i-k+1;
        if(h<=t && q[h]<j)h++;
        while(h<=t && a[i]>=a[q[t]])t--;
        q[++t]=i;
        if(j>=1)cout<<a[q[h]]<<" ";
    }

数学

乘法逆元

a b % m o d = a ∗ i n v ( b ) % m o d \frac{a}{b} \% mod = a * inv(b) \% mod ba%mod=ainv(b)%mod

  • 费马小(mod为质数)
    i n v ( b ) = b m o d − 2 % m o d inv(b) = b^{mod-2}\%mod inv(b)=bmod2%mod
  • 扩展欧几里得法
void exgcd(ll a, ll b, ll &x, ll &y)
{
    if (b == 0)
    {
        x = 1, y = 0;
        return;
    }
    exgcd(b, a % b, y, x);
    y -= a / b * x;
}
ll inv(ll n)
{
    ll x, y;
    exgcd(n, mod, x, y);
    return x;
}
  • 线性逆元
    vector<int> inv(n + 1);
    inv[1] = 1;
    for (int i = 2; i <= n; ++i)
    {
        inv[i] = (long long)(mod - mod / i) * inv[mod % i] % mod;
    }

筛法

  • 线性筛
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e6+5;
int p[N],cnt,v[N];
int main() {
    int n;
    cin>>n;
    for(int i=2;i<=n;i++){
        if(!v[i]){
            p[cnt++]=i;
        }
        for(int j=0;p[j]*i<=n;j++){
            v[p[j]*i]=p[j];
            if(i%p[j]==0)break;
        }
    }
    
    cout<<cnt;
};

分解质因数

时间复杂度: n \sqrt{n} n

// 首先,对于每个x%i 一定是质数,因为如果(2~i-1)的数字都被除掉了,所以满足if件i不可能是合数。
// 其次,大于sqrt(n)的因子只可能有1个,所以只需要遍历到sqrt(n)就行了,剩下一个如果x>1 那么x就是大于sqrt的质因子
void solve(){
    int x;
    cin>>x;
    for(int i=2;i<=x/i;i++){
        int cnt=0;
        while(x%i==0){
            x/=i;
            cnt++;
        }
        if(cnt)cout<<i<<" "<<cnt<<endl;
    }
    if(x>1)cout<<x<<" "<<1<<endl;
    cout<<endl;
}

欧拉函数

公式:1~N 与N互质的个数为欧拉函数
p h i ( N ) = N ∗ p 1 − 1 p 1 . . . p m − 1 p m phi(N)=N*\frac{p_1-1}{p_1}...\frac{p_m-1}{p_m} phi(N)=Np1p11...pmpm1

  1. g c d ( a , b ) = 1 gcd(a,b)=1 gcd(a,b)=1时, ϕ ( a ) ∗ ϕ ( b ) = ϕ ( a b ) \phi(a)*\phi(b)=\phi(ab) ϕ(a)ϕ(b)=ϕ(ab)
  2. a ∣ b a|b ab时, ϕ ( a b ) = ϕ ( a ) ∗ b \phi(ab)=\phi(a)*b ϕ(ab)=ϕ(a)b
  3. p p p是质数, ϕ ( p n ) = p n − 1 ∗ ( p − 1 ) \phi(p^n)=p^{n-1}*(p-1) ϕ(pn)=pn1(p1)

  1. 求解 ϕ ( n ) \phi(n) ϕ(n)
    思路:试除法求质因子,求的过程中计算即可,时间复杂度 O ( n ) O(\sqrt{n}) O(n )
   int n;
   cin>>n;
   ll res=n;
   for(int i=2;i<=n/i;i++){
       if(n%i==0)res=res/i*(i-1);
       while(n%i==0)n/=i;
   }
   if(n>1)res=res/n*(n-1);
   cout<<res<<endl;
  1. 求解 ∑ i = 1 n ϕ ( i ) \sum_{i=1}^n\phi(i) i=1nϕ(i)

    思路:可以用埃氏筛法或线性筛法,要运用到上面推导的三个性质。

  • 埃氏筛法
/*
埃氏筛法的过程中,我们对质数进行翻倍,那么每个数字会被自己所有的质因子筛一遍,我们根据这个性质来“顺便”求解欧拉函数
*/
#include <iostream>
const int N=1e6+5;
int phi[N];
int main()
{  
    int n;
    cin>>n;
    long long  res=1;
    for(int i=1;i<=n;i++)phi[i]=i;
    for(int i=2;i<=n;i++){
        if(phi[i]==i){
            for(int j=i;j<=n;j+=i){
                phi[j]=phi[j]/i*(i-1);
            }
        }
        res+=phi[i];
    }
    cout<<res;
}
  • 线性筛法
/*
利用线性筛法的特点:每个数字有且仅被最小质因子筛一遍
*/
#include <iostream>
const int N=1e6+5;
typedef long long ll;
using namespace std;
int phi[N]={0,1};
int p[N],cnt;
bool book[N];
int main()
{  
    int n;
    cin>>n;
    ll res=1;
    for(int i=2;i<=n;i++){
        if(phi[i]==0)p[++cnt]=i,phi[i]=i-1;//没被筛到过,表明是质数 性质三
        for(int j=1;p[j]<=n/i;j++){
            if(i%p[j]==0){
                phi[i*p[j]]=phi[i]*p[j];//性质2  
                break;
            }
            phi[i*p[j]]=phi[i]*phi[p[j]];//性质1  phi[p[j]]在之前以及被计算过
        }
        res+=phi[i];
    }
    cout<<res;
}

中国剩余定理

字符串

字符哈希

#include<bits/stdc++.h>
using namespace  std;
typedef long long ll;
typedef unsigned long long ull ;//2^64-1;
//给你一个数字s,s<1e10,有q(q<1e6)次询问,每次询问两个区间[a~b] [c~d],求这段区间的数字是否相同;
const int N=1e6+5;
const int P=131;//131 13331
// mod=2^64  %mod %mod
char s[N];
ull hs[N],p[N]={1}; //p[i]=10^i=p^i
ull getHV(int l,int r ){//得到区间[l~r]的哈希值;
    return hs[r]-hs[l-1]*p[r-l+1];
}
int main(){
    int q;
    scanf("%s",s+1);//下标1开始;
    int n=strlen(s+1);
    for(int i=1;i<=n;i++){
        hs[i]=hs[i-1]*P+s[i];
        p[i]=p[i-1]*P;
    }
    scanf("%d",&q);
    while(q--){
        int a,b,c,d;
        scanf("%d%d%d%d",&a,&b,&c,&d);
        if(getHV(a,b)==getHV(c,d)){
            cout<<"Yes\n";
        }
        else{
            cout<<"No\n";
        }

    }
}

KMP

    scanf("%s",s+1);
    scanf("%s",p+1);
    int ls=strlen(s+1),lp=strlen(p+1);
    //先求出匹配串的next数组
    for(int i=2,j=0;i<=lp;i++){
        while(j && p[j+1]!=p[i])j=ne[j];
        if(p[j+1]==p[i])j++;
        ne[i]=j;
    }
    //再用得到的next 去匹配s
    for(int i=1,j=0;i<=ls;i++){
        while(j && p[j+1]!=s[i])j=ne[j];
        if(p[j+1]==s[i])j++;
        if(j==lp){//匹配成功
            cout<<i-lp+1<<endl;
            j=ne[j];
        }
    }

数据结构

Trie

const int N=100005;
//最坏情况下,每个字符都要再新节点,因此N取输入字符总数; 26取决字符的范围
int trie[N][26],idx,ed[N];
void insert(char * str){
    int p=0;//0代表树根;
    for(int i=0;str[i];i++){
        int ch=str[i]-'a';
        if(!trie[p][ch]){
            trie[p][ch]=++idx;
        }
        p=trie[p][ch];
    }
    ed[p]++;
}
bool search(char * str){
    int p=0;
    for(int i=0;str[i];i++){
        int ch=str[i]-'a';
        if(!trie[p][ch])return false;
        p=trie[p][ch];
    }
    return ed[p];
}

ST表

st表是一种能够很好地完成一种特定的RMQ的算法。
因为局限性比较大,不能反复修改但是时间复杂度非常优秀。
预处理 O ( n l o g 2 n ) O(nlog_2n) O(nlog2n) 查询 O ( 1 ) O(1) O(1)
S T M a x [ i ] [ j ] STMax[i][j] STMax[i][j]​:从 i i i​开始的区间长度为 2 j 2^j 2j​的最大值,即区间范围为 [ i , i + 2 j − 1 ] [i,i+2^j-1] [i,i+2j1]​​。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+5;
int STMax[N][23];
int lg[N];
int query(int l,int r ){
    int k=lg[r-l+1];
    return max(STMax[l][k],STMax[r-(1<<k)+1][k]);
}

int main() {
    int n,m;
    for(int i=2;i<N;i++){
        lg[i]=lg[i/2]+1;
    }
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){
        scanf("%d",&STMax[i][0]);
    }
    for(int j=1;j<=lg[n];j++){
        for(int i=1;i+(1<<j)-1<=n;i++){
            STMax[i][j]=max(STMax[i][j-1],STMax[i+(1<<(j-1))][j-1]);
        }
    }
    while(m--){
        int l,r;
        scanf("%d%d",&l,&r);
        printf("%d\n",query(l,r));
    }

}

并查集

  • 查询
int find(int x)
{
    f[x]==x? x:f[x]=find(f[x]);
}
  • 合并
void merge(int i, int j)
{
    fa[find(i)] = find(j);
}

分块

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N =5e5+5;
const int M =N;
int a[N],bl[N];
int st[M],ed[M];
ll sum[M];
int bn;
void init(int n){
    bn = sqrt(n);
    for(int i = 1; i <= bn; i++){
        st[i] = bn * (i-1) + 1;
        ed[i] = bn * i;
    }
    ed[bn]=n;//把最后的放最后一块里
    for(int i = 1; i <= bn; i++){
        for(int j = st[i]; j <= ed[i]; j++){
            bl[j] = i;
            sum[i] += a[j];
        }
    }
}
ll ask(int l, int r){
    ll res = 0;
    int lbk = bl[l], rbk = bl[r];
    if(lbk == rbk){
        for(int i = l; i <= r ; i++){
            res += a[i];
        }
    }
    else{
        for(int i = l; i <= ed[lbk]; i++){
            res += a[i];
        }
        // cout<<res<<endl;
        for(int i = lbk + 1; i <= rbk - 1; i++){
            res += sum[i];
        }
        // cout<<res<<endl;
        for(int i = st[rbk]; i <= r; i++){
            res += a[i];
        }
        // cout<<res<<endl;

    }
    return res;

}
int main(){
    ios_base::sync_with_stdio(false);
    cin.tie(0);	
    int n, m;
    cin >> n >> m;
    for(int i = 1; i <= n; i ++){
        cin>>a[i];
    }
    init(n);//初始化要崽读入之后 
    for(int i = 1; i <= m; i++){
        int op, x, y;
        cin >> op >> x >> y;
        if(op == 1){
            a[x]+=y;
            sum[bl[x]]+=y;
        }
        else{
            cout<<ask(x,y)<<endl;
        }
    }
}   

树状数组

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N =5e5+5;
int a[N];
ll c[N];
int lowbit(int i){
    return i &- i;
}
void add(int x, int y){
    for(int i = x; i < N; i += i & -i){
        c[i] += y;
    }
}

ll ask(int x){
    ll res =0;
    for(int i = x; i; i -= i & -i){
        res += c[i];
    }
    return res;
}
int main(){
   int n,m;
   cin >> n >> m;
   for(int i=1;i<=n;i++){
       int y;
       cin >> y;
       add(i, y);
   }
   while(m -- ){
       int op,x,y;
       cin >> op >> x >> y;
       if(op == 1){
           add(x , y);
       }
       else{
           cout << ask(y) - ask(x-1) << endl;
       }
   }
}

差分树状数组

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N =5e5+5;
int a[N];
int df[N];
ll c[N];
int lowbit(int i){
    return i &- i;
}
void add(int x, int y){
    for(int i = x; i < N; i += i & -i){
        c[i] += y;
    }
}

ll ask(int x){
    ll res =0;
    for(int i = x; i; i -= i & -i){
        res += c[i];
    }
    return res;
}
int main(){
   int n,m;
   cin >> n >> m;
   for(int i=1;i<=n;i++){
       cin >> a[i];
   }
   while(m -- ){
       int op,x,y;
       cin >> op ;
       if(op == 1){
           int k;   
           cin >> x >> y >> k;
           add(x , k);
           add(y+1 , -k);
       }
       else{
           cin >> x;
           cout << a[x] + ask(x) << endl;
       }
   }
}

线段树

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N =5e5+5;
struct tree{
    int l, r;
    ll dat;
}t[N*4];
int a[N];
void build(int p, int l, int r){
    t[p].l = l, t[p].r = r;
    if(l == r){
        t[p].dat = a[l];
        return;
    }
    int mid = l + r >> 1;
    build(p * 2, l, mid);
    build(p * 2 + 1, mid + 1, r);
    t[p].dat = max(t[p*2].dat , t[p*2+1].dat);
}
void change(int p,int x, int v){
    if(t[p].l == t[p].r){
        t[p].dat += v;
        return;
    }
    int mid = t[p].l + t[p].r >> 1;
    if(x <= mid) change(p * 2, x, v);
    else change(p * 2 + 1, x, v);
    t[p].dat = max(t[p*2].dat , t[p*2+1].dat);
}

ll ask(int p, int l, int r){
    if(l <= t[p].l && r >= t[p].r)return t[p].dat;
    int mid = t[p].l + t[p].r >> 1;
    ll val = 0;
    if(l <= mid) val = max(val,ask(p*2, l, r));
    if(r > mid) val = max(val,ask(p*2, l, r));
    return val;
}
int main(){
    ios_base::sync_with_stdio(false);
    cin.tie(0);	
    int n, m;
    cin >> n >> m;
    for(int i = 1; i <= n; i ++){
        cin >> a[i];
    }
    build(1, 1, n);
    for(int i = 1; i <= m; i++){
        int op, x, y;
        cin >> op >> x >> y;
        if(op == 1){
            change(1, x, y);
        }
        else{
            cout<<ask(1, x, y)<<endl;
        }
    }
}

图论

最小生成树

  • 克鲁斯卡尔
void solve()
{
    //求生成树,带个数权重的
    int n, m;
    cin >> n >> m;
    vector<int> f(n + 1), s(n + 1, 1);
    vector<vector<pii>> g(n + 1);
    for (int i = 1; i <= n; i++)
        f[i] = i;
    auto find = [&](auto find, int i) -> int
    {
        if (i == f[i])
            return i;
        return f[i] = find(find, f[i]);
    };
    vector<pair<int, pii>> r;
    for (int i = 1; i <= m; i++)
    {
        int a, b, c;
        cin >> a >> b >> c;
        r.push_back({c, {a, b}});
    }
    sort(r.begin(), r.end());
    ll sum = 0;
    for (auto i : r)
    {
        int a = i.second.first, b = i.second.second, c = i.first;
        int fa = find(find, a), fb = find(find, b);
        if (fa != fb)
        {
            f[fb] = fa;
            s[fa] += s[fb];
            sum += c;
        }
    }
    if (s[find(find, 1)] == n)
        cout << sum << "\n";
    else
        cout << "orz\n";
}
  • 普林姆

链式前向星

#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
const int N=1e5+5;//顶点数;
int h[N],e[N],ne[N],idx;
int v[N];
void add(int a,int b){
    e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}

拓扑排序

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+5;
int h[N],e[N],ne[N],idx;
int d[N];//入度
int v[N];
vector<int>res;
void add(int a,int b){
    e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
//进阶版本
void tp(int n){//n个顶点;
    queue<int>q;
    for(int i=1;i<=n;i++){//首先把所有入度为0的点 放入队列之中;
        if(d[i]==0)
        q.push(i);
    }
    while(!q.empty()){//删掉所有入度为0的点的出边
        int t=q.front();
        q.pop();
        res.push_back(t);     
        for(int i=h[t];i!=-1;i=ne[i]){ //遍历t的出边
            int j=e[i];
            if(--d[j]==0){
                q.push(j);
            }
        }
    }
    if(res.size()!=n) cout<<"no!"; //判断是否有没输出的===>有环;
    else{
        for(int i:res) cout<<i<<" ";
    }
}

二分图

染色法判定二分图
bool dfs(int x,int c){
    color[x]=c;
    for(int i=h[x];i!=-1;i=ne[i]){
        int j=e[i];
        if(!color[j]){
            int m=dfs(j,3-c);
            if(m)return true;
        }
        else{
            if(c==color[j]){
                return true;
            }
        }
    }
    return false;
}
匈牙利算法(二分图最大匹配)

时间复杂度 O ( n m ) O(nm) O(nm)

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int h[505],match[505],st[505];
int e[N],ne[N],idx;
void add(int a,int b){
    e[++idx]=b,ne[idx]=h[a],h[a]=idx;
}
bool find(int x){
    for(int i=h[x];i;i=ne[i]){
        int j=e[i];
        if(!st[j]){
            st[j]=1;
            if(!match[j] || find(match[j])){
                match[j]=x;
                return true;
            }
        }
    }
}

int main(){
    int n1,n2,m;
    cin>>n1>>n2>>m;
    for(int i=1;i<=m;i++){
        int a,b;
        cin>>a>>b;
        add(a,b);
    }
    int res=0;
    for(int i=1;i<=n1;i++){
        memset(st,0,sizeof st);
        res+=find(i);
    }
    cout<<res;
}

最短路

双端队列求解01图
int dj(){
    memset(v,0,sizeof v);
    int end=(r+1)*(c+1);//终点
    //双端队列求解;
    deque<node>q;
    q.push_back({1,0});
    while(!q.empty()){
        node t=q.front();
        q.pop_front();
        v[t.id]=1;//出来的时候才能标记  因为怕权重1的标记了丢后面 0的反而访问不了
        if(t.id==end)return t.dis;
        for(int i=h[t.id];i;i=ne[i]){
            int j=e[i];
            if(!v[j]){
                if(w[i]==1){
                    q.push_back({j,t.dis+1});
                }
                else{
                    q.push_front({j,t.dis});
                }
            }
        }
    }
    return -1;
}
朴素迪杰斯特拉
#include<bits/stdc++.h>
using namespace std;
const int N=505;
int inf=0x3f3f3f3f;
int r[N][N];
int n,m;
int v[N],dis[N];
int dj(){
   memset(dis,0x3f,sizeof dis);
   dis[1]=0;//表示起点是1
   for(int i=1;i<=n;i++){//执行n次 固定
       int id=-1;
       for(int j=1;j<=n;j++){
           if(!v[j] && (id==-1 || dis[id]>dis[j])){
               id=j;
           }
       }
       v[id]=1;//根据这点进行松弛
       for(int j=1;j<=n;j++){
          dis[j]=min(dis[j],dis[id]+r[id][j]);
       }
   }
   if(dis[n]>inf/2)return -1;
   return dis[n];
}
int main(){
    memset(r,0x3f,sizeof r);
    cin>>n>>m;
    for(int i=1;i<=m;i++){
        int a,b,c;
        cin>>a>>b>>c;
        r[a][b]=min(r[a][b],c);
    }
    cout<<dj();
}
优先队列优化迪杰斯特拉
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+5;
typedef long long ll;
const int inf =0x3f3f3f3f;
int n,m;
int e[N],h[N],w[N],ne[N],idx,v[N],dis[N];
void add(int a,int b,int c){
    e[++idx]=b,w[idx]=c;
    ne[idx]=h[a],h[a]=idx;
}
struct node{
  int id,dis;
  bool operator < (const node b )const {
      return dis>b.dis;
  }
};
int dj(){
    memset(dis,0x3f,sizeof dis);
    priority_queue<node,vector<node>>q;
    q.push({1,0});
    while(!q.empty()){
        auto t=q.top();
        q.pop();
        if(v[t.id])continue;
        v[t.id]=1;//一定要在取出来的时候才能固定 因为放进去只代表被更新
        for(int i=h[t.id];i;i=ne[i]){
            int j=e[i];
            if(!v[j] && dis[j]>t.dis+w[i]){
                dis[j]=t.dis+w[i];
                q.push({j,dis[j]});
            }
        }
    }
    if(dis[n]>inf/2)return -1;
    return dis[n];
}

int main(){
    cin>>n>>m;
    for(int i=1;i<=m;i++){
        int a,b,c;
        cin>>a>>b>>c;
        add(a,b,c);
    }
    cout<<dj();

}
bellman-ford

适用于有边限制的最短路,也适用于负权图

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=505;
int n,m,k;
int dis[N];
struct node{
    int a,b,c;
}r[10005];
void bellman_ford(){
    memset(dis,0x3f,sizeof dis);
    dis[1]=0;
    int cp[N]={};
    for(int i=1;i<=k;i++){
        memcpy(cp,dis,sizeof dis);
        for(int j=1;j<=m;j++){
            int a=r[j].a,b=r[j].b,c=r[j].c;
            if(cp[b]>cp[a]+c)dis[b]=cp[a]+c;
        }
    }
    if(dis[n]>0x3f3f3f3f/2)cout<<"impossible"<<endl;
    else cout<<dis[n]<<endl;
}
int main(){
    scanf("%d%d%d",&n,&m,&k);
    for(int i=1;i<=m;++i){
        int a,b,c;
        scanf("%d%d%d",&a,&b,&c);
        r[i]={a,b,c};
    }
    bellman_ford();
}


SPFA
void spfa(){
    memset(dis,0x3f,sizeof dis);
    queue<int>q;
    q.push(1);
    dis[1]=0;
    while(!q.empty()){
        int t=q.front();
        q.pop();
        v[t]=0;//用来是否已在队列里面,如果已经在了,就不要反复添加。 可以提高效率
        for(int i=h[t];i;i=ne[i]){
            int j=e[i];
            if(dis[j]>dis[t]+w[i]){
                dis[j]=dis[t]+w[i];
                if(!v[j])q.push(j),v[j]=1;
            }
        }
    }
    if(dis[n]>inf/2)cout<<"impossible";
    else cout<<dis[n];
}
  • 判断负环
void spfa(){
    memset(dis,0x3f,sizeof dis);
    queue<int>q;
    for(int i=1;i<=n;i++){
        q.push(i);
        v[i]=1;
    }
    while(!q.empty()){
        int t=q.front();
        q.pop();
        v[t]=0;
        for(int i=h[t];i!=-1;i=ne[i]){
            int j=e[i];
            if(w[i]+dis[t]<dis[j]){
                dis[j]=w[i]+dis[t];
                cnt[j]=cnt[t]+1;
                if(cnt[j]>=n){ //用cnt记录,最多被优化n次,不可能一直被优化
                    cout<<"Yes";
                    return ;
                }
                if(!v[j]){
                    q.push(j);
                    v[j]=1;
                }
            }
        }
    }
    cout<<"No";
}
Floyd
    memset(r,0x3f,sizeof r);
    for(int k=1;k<=n;k++){
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                if(i==j)r[i][j]=0;
                else r[i][j]=min(r[i][j],r[i][k]+r[k][j]);
            }
        }
    }
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值