板子們。。。。

沙雕的gcd:node

//1.gcd
int gcd(int a,int b) {
    return b?gcd(b,a%b):a;
}
View Code

還有個exgcd:ios

//2.擴展gcd )extend great common divisor
ll exgcd(ll l,ll r,ll &x,ll &y) {
    if(r==0) {
        x=1;
        y=0;
        return l;
    } else {
        ll d=exgcd(r,l%r,y,x);
        y-=l/r*x;
        return d;
    }
}
View Code

求逆元:c++

//3.求a關於m的乘法逆元
ll mod_inverse(ll a,ll m) {
    ll x,y;
    if(exgcd(a,m,x,y)==1)//ax+my=1
        return (x%m+m)%m;
    return -1;//不存在
}

快速冪:git

//4.快速冪quick power
ll qpow(ll a,ll b,ll m) {
    ll ans=1;
    ll k=a;
    while(b) {
        if(b&1)ans=ans*k%m;
        k=k*k%m;
        b>>=1;
    }
    return ans;
}

快速乘(也叫二分乘法):算法

//5.快速乘,直接乘會爆ll時須要它,也叫二分乘法。
ll qmul(ll a,ll b,ll m) {
    ll ans=0;
    ll k=a;
    ll f=1;//f是用來存負號的
    if(k<0) {
        f=-1;
        k=-k;
    }
    if(b<0) {
        f*=-1;
        b=-b;
    }
    while(b) {
        if(b&1)
            ans=(ans+k)%m;
        k=(k+k)%m;
        b>>=1;
    }
    return ans*f;
}

中國剩餘定理:數組

//6.中國剩餘定理CRT (x=ai mod mi)
ll china(ll n, ll *a,ll *m) {
    ll M=1,y,x=0,d;
    for(ll i = 1; i <= n; i++) M *= m[i];
    for(ll i = 1; i <= n; i++) {
        ll w = M /m[i];
        exgcd(m[i], w, d, y);//m[i]*d+w*y=1
        x = (x + y*w*a[i]) % M;
    }
    return (x+M)%M;
}

篩素數:app

//7.篩素數,全局:int cnt,prime[N],p[N];
void isprime() {
    cnt = 0;
    memset(prime,true,sizeof(prime));
    for(int i=2; i<N; i++) {
        if(prime[i]) {
            p[cnt++] = i;
            for(int j=i+i; j<N; j+=i)
                prime[j] = false;
        }
    }
}

快速計算逆元:ide

//8.快速計算逆元
//補充:>>關於快速算逆元的遞推式的證實<< 
void inverse() {
    inv[1] = 1;
    for(int i=2; i<N; i++) {
        if(i >= M) break;
        inv[i] = (M-M/i)*inv[M%i]%M;
    }
}

組合數取模:函數

//9.組合數取模
n和m 10^5時,預處理出逆元和階乘
ll fac[N]= {1,1},inv[N]= {1,1},f[N]= {1,1};
ll C(ll a,ll b) {
    if(b>a)return 0;
    return fac[a]*inv[b]%M*inv[a-b]%M;
}
void init() { //快速計算階乘的逆元
    for(int i=2; i<N; i++) {
        fac[i]=fac[i-1]*i%M;
        f[i]=(M-M/i)*f[M%i]%M;
        inv[i]=inv[i-1]*f[i]%M;
    }
}
n較大10^9,可是m較小10^5時,
ll C(ll n,ll m) {
    if(m>n)return 0;
    ll ans=1;
    for(int i=1; i<=m; i++)
        ans=ans*(n-i+1)%M*qpow(i,M-2,M)%M;
    return ans;
}

//n和m特別大10^18時可是p較小10^5時用lucas

Lucas大組合取模:oop

//10.Lucas大組合取模 

#define N 100005
#define M 100007
ll n,m,fac[N]= {1};
ll C(ll n,ll m) {
    if(m>n)return 0;
    return fac[n]*qpow(fac[m],M-2,M)%M*qpow(fac[n-m],M-2,M)%M;//費馬小定理求逆元
}
ll lucas(ll n,ll m) {
    if(!m)return 1;
    return(C(n%M,m%M)*lucas(n/M,m/M))%M;
}
void init() {
    for(int i=1; i<=M; i++)
        fac[i]=fac[i-1]*i%M;
}

質因數分解:

//11.質因數分解
cin>>n;
for(int i=2; i<=n; i++) {
    if(n==0)break;
    while(n%i==0) {
        n/=i;
        k[++ans]=i;
    }
}

試除法:

//12.試除法
bool check(int n) {
    if(n==1)return false;
    for(int i=2; i<=sqrt(n); ++i)
        if(n%i==0)return false;
    return true;
}

miller-rabin算法:

//13.miller-rabin算法
int test[10]= {2,3,5,7,11,13,19,23};
int qpow(int a,int b,int p) {
    int ans=1;
    while(b) {
        if(b&1)ans=1ll*ans*a%p;
        a=1ll*a*a%p,b>>=1;
    }
    return ans;
}
bool miller_rabin(int p) {
    if(p==1)return 0;
    int t=p-1;
    k=0;
    while(!(t&1))k++,t>>=1;
    for(int i=0; i<8; ++i) {
        if(p==test[i])return 1;
        long long a=qpow(test[i],t,p,),nx=a;
        for(int j=1; j<=k; ++j) {
            nx=(a*a)%p;
            if(nx==1&&a!=1&&a!=p-1)
                return 0;
            a-nx;
        }
        if(a!=1)return 0;
    }
    return 1;
}

快讀:

//14.快讀

inline int read() {
    int s=0,w=1;
    char ch=getchar();
    while(ch<'0'||ch>'9') {
        if(ch=='-')w=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9')
        x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
    return s*w;
}

spfa_dfs:

//15.spfa_dfs

int spfa_dfs(int u) {
    vis[u]=1;
    for(int k=f[u]; k!=0; k=e[k].next) {
        int v=e[k].v,w=e[k].w;
        if( d[u]+w < d[v] ) {
            d[v]=d[u]+w;
            if(!vis[v]) {
                if(spfa_dfs(v))
                    return 1;
            } else
                return 1;
        }
    }
    vis[u]=0;
    return 0;
}

spfa_dfs:

//1六、spfa_bfs
int spfa_bfs(int s) {
    queue <int> q;
    memset(d,0x3f,sizeof(d));
    d[s]=0;
    memset(c,0,sizeof(c));
    memset(vis,0,sizeof(vis));

    q.push(s);
    vis[s]=1;
    c[s]=1;
    //頂點入隊vis要作標記,另外要統計頂點的入隊次數
    int OK=1;
    while(!q.empty()) {
        int x;
        x=q.front();
        q.pop();
        vis[x]=0;
        //隊頭元素出隊,而且消除標記
        for(int k=f[x]; k!=0; k=nnext[k]) { //遍歷頂點x的鄰接表
            int y=v[k];
            if( d[x]+w[k] < d[y]) {
                d[y]=d[x]+w[k];  //鬆弛
                if(!vis[y]) { //頂點y不在隊內
                    vis[y]=1;    //標記
                    c[y]++;      //統計次數
                    q.push(y);   //入隊
                    if(c[y]>NN)  //超過入隊次數上限,說明有負環
                        return OK=0;
                }
            }
        }
    }

    return OK;

}

歐拉函數:

 1 for(i=1; i<=maxn; i++)
 2     p[i]=i;
 3 for(i=2; i<=maxn; i+=2)
 4     p[i]/=2;
 5 for(i=3; i<=maxn; i+=2)
 6     if(p[i]==i)
 7     {
 8         for(j=i; j<=maxn; j+=i)
 9             p[j]=p[j]/i*(i-1);
10     }

 裴蜀定理:

1 std::cin>>n;
2 for(int i=1;i<=n;i++){
3     int x;
4     std::cin>>x;
5     x=std::abs(x);
6     ans=gcd(ans,x);
7 }
8 std::cout<<ans;
9 PS:本身敲的

 

雜:

//cin,優化
cin.tie(0);
ios_base::sync_with_stdio(false);
//輸出優化:
void print( int k ) {
    num = 0;
    while( k > 0 ) ch[++num] = k % 10, k /= 10;
    while( num )
        putchar( ch[num--]+48 );
    putchar( 32 );
}

RMQ:

//區間查詢最值問題
//預處理
void rmq_init() {
    for(int i=1; i<=N; i++)
        dp[i][0]=arr[i];//初始化
    for(int j=1; (1<<j)<=N; j++)
        for(int i=1; i+(1<<j)-1<=N; i++)
            dp[i][j]=min(dp[i][j-1],dp[i+(1<<j-1)][j-1]);

}
//查詢 
int rmq(int l,int r) {
    int k=log2(r-l+1);
    return min(dp[l][k],dp[r-(1<<k)+1][k]);
}

RMQ轉LCA:

int euler[MAXN*2];
int dep[MAXN*2];
int pos[MAXN];
int top;
int rmq[MAXN*2][16];
void dfs(int u,int depth,int fa)
{
    euler[++top]=u;
    dep[top]=depth;
    pos[u]=top;
    INE(i,u,e)
    {
        int v=e[i].v;
        if(v==fa) continue;
        dfs(v,depth+1,u);
        euler[++top]=u;
        dep[top]=depth;
    }
}
void RMQinit()
{
    rep(i,1,top) rmq[i][0]=i;
    rep(j,1,16)
    rep(i,1,top) if(i+(1<<j)-1<=top)
    {
        if(dep[rmq[i][j-1]]<dep[rmq[i+(1<<j-1)][j-1]])
            rmq[i][j]=rmq[i][j-1];
        else
            rmq[i][j]=rmq[i+(1<<j-1)][j-1];
    }
}
int RMQ(int l,int r)
{
    int len=r-l+1;
    int LOG=0;
    for(;1<<LOG+1<=len;LOG++);
    if(dep[rmq[l][LOG]]<dep[rmq[r-(1<<LOG)+1][LOG]])
        return rmq[l][LOG];
    else
        return rmq[r-(1<<LOG)+1][LOG];
}
void LCAinit()
{
    dfs(1,0,-1);
    RMQinit();
}
int LCA(int u,int v)
{
    if(pos[u]>pos[v]) swap(u,v);
    return euler[RMQ(pos[u],pos[v])];
} 

tarjan求LCA:

//並查集記錄父親的數組.
int father[MAXN];

//並查集的查找函數,有路徑壓縮功能.
int find ( int x ) {
    return father[x] == x ? x : father[x] = find ( father[x]);
}

//採用鄰接表存儲
struct {
    int v,next,lca,u;
} e[2][MAXN<<2];

//分別記錄邊對和查詢數對
int head[2][MAXN];
int cc;

//添加邊,flag表示模式
void add ( int flag , int u , int v ) {
    e[flag][cc].u = u;
    e[flag][cc].v = v;
    e[flag][cc].next = head[flag][u];
    head[flag][u] = cc++;
}
//標記當前點是否訪問過
bool visited[MAXN];

void LCA ( int u ) {
    father[u] = u;
    visited[u] = true;
    //深度優先搜索整棵樹
    for ( int i = head[0][u]; i != -1 ; i = e[0][i].next ) {
        int v = e[0][i].v;
        if ( visited[v] ) continue;
        LCA ( v );
        //從葉節點開始,逐層標記父節點
        father[v] = u;
    }
    //當前子樹已經維護,利用並查集找到當前子樹的查詢數對的LCA
    for ( int i = head[1][u]; i != -1 ; i = e[1][i].next ) {
        int v = e[1][i].v;
        if ( !visited[v] ) continue;
        //若是當前u,v都已經訪問過,那麼必定維護過的子樹中
        e[1][i].lca = e[1][i^1].lca = find ( v );
    }
}

倍增求LCA:

#include<bits/stdc++.h>
using namespace std;
struct node {
    int t,nex;
} e[500001<<1];
int depht[500001],father[500001][22],lg[500001],head[500001];
int tot;
inline void add(int x,int y) {
    e[++tot].t=y;
    e[tot].nex=head[x];
    head[x]=tot;
}
inline void dfs(int now,int fath) {
    depht[now]=depht[fath]+1;
    father[now][0]=fath;
    for(register int i=1; (1<<i)<=depht[now]; ++i)
        father[now][i]=father[father[now][i-1]][i-1];
    for(register int i=head[now]; i; i=e[i].nex) {
        if(e[i].t!=fath)dfs(e[i].t,now);
    }
}
inline int lca(int x,int y) {
    if(depht[x]<depht[y])
        swap(x,y);
    while(depht[x]>depht[y])
        x=father[x][lg[depht[x]-depht[y]]-1];
    if(x==y)
        return x;
    for(register int k=lg[depht[x]]; k>=0; --k)
        if(father[x][k]!=father[y][k])
            x=father[x][k],y=father[y][k];
    return father[x][0];
}
int n,m,s;
int main() {
    scanf("%d%d%d",&n,&m,&s);
    for(register int i=1; i<=n-1; ++i) {
        int x,y;
        scanf("%d%d",&x,&y);
        add(x,y);
        add(y,x);
    }
    dfs(s,0);
    for(register int i=1; i<=n; ++i)
        lg[i]=lg[i-1]+(1<<lg[i-1]==i);
    for(register int i=1; i<=m; ++i) {
        int x,y;
        scanf("%d%d",&x,&y);
        printf("%d\n",lca(x,y));
    }
    return 0;
}

 

#include <bits/stdc++.h>

using namespace std;

#define INF 0x3f3f3f3f
#define MAXN 1000010
#define MAXM 5010

inline int read()
{
    int x = 0,ff = 1;char ch = getchar();
    while(!isdigit(ch))
    {
        if(ch == '-') ff = -1;
        ch = getchar();
    }
    while(isdigit(ch))
    {
        x = (x << 1) + (x << 3) + (ch ^ 48);
        ch = getchar();
    }
    return x * ff;
}

inline void write(int x)
{
    if(x < 0) putchar('-'),x = -x;
    if(x > 9) write(x / 10);
    putchar(x % 10 + '0');
}

int a,ti = 0,cnt = 0,fa[MAXN],vis[MAXN],loop[MAXN];
int lin[MAXN],tot = 0;
struct edge
{
    int y,v,next;
}e[MAXN];

inline void add(int xx,int yy,int vv)
{
    e[++tot].y = yy;
    e[tot].v = vv;
    e[tot].next = lin[xx];
    lin[xx] = tot;
}

void get_loop(int x)
{
    vis[x] = ++ti;
    for(int i = lin[x],y;i;i = e[i].next)
    {
        if((y = e[i].y) == fa[x]) continue;
        if(vis[y])
        {
            if(vis[y] < vis[x]) continue;
            loop[++cnt] = y;
            for(y = fa[y];y != fa[x];y = fa[y])
            loop[++cnt] = y;    
        }
        else fa[y] = x,get_loop(y);
    }
} 

int main()
{
    a = read();
    for(int i = 1;i <= a;++i)
    {
        int y,v;
        y = read(); v = read();
        add(i,y,v);
        add(y,i,v);
    }
    get_loop(1);
    for(int i = 1;i <= cnt;++i)
    write(loop[i]),putchar(' '); 
    return 0;
}
基環樹找環

 

//18.tarjan
void Tarjan ( int x ) {
    dfn[ x ] = ++dfs_num ;
    low[ x ] = dfs_num ;
    vis [ x ] = true ;//是否在棧中
    stack [ ++top ] = x ;
    for ( int i=head[ x ] ; i!=0 ; i=e[i].next ) {
        int temp = e[ i ].to ;
        if ( !dfn[ temp ] ) {
            Tarjan ( temp ) ;
            low[ x ] = gmin ( low[ x ] , low[ temp ] ) ;
        } else if ( vis[ temp ])low[ x ] = gmin ( low[ x ] , dfn[ temp ] ) ;
    }
    if ( dfn[ x ]==low[ x ] ) {//構成強連通份量
        vis[ x ] = false ;
        color[ x ] = ++col_num ;//染色
        while ( stack[ top ] != x ) {//清空
            color [stack[ top ]] = col_num ;
            vis [ stack[ top-- ] ] = false ;
        }
        top -- ;
    }
}
tarjan模板

 

#include<bits/stdc++.h>
#define MAXN 501
const int Big_B = 10; const int Big_L = 1;
inline int intcmp_ (int a, int b) { if (a > b) return 1; return a < b ? -1 : 0; }
struct Int 
{
#define rg register
    inline int max (int a, int b) { return a > b ? a : b; }
    inline int min (int a, int b) { return a < b ? a : b; }
    std :: vector <int> c; Int () {} typedef long long LL; 
    Int (int x) { for (; x > 0; c.push_back (x % Big_B), x /= Big_B); }
    Int (LL x) { for (; x > 0; c.push_back (x % Big_B), x /= Big_B); }
    inline void CrZ () { for (; !c.empty () && c.back () == 0; c.pop_back ()); }
    inline Int &operator += (const Int &rhs){
        c.resize (max (c.size (), rhs.c.size ())); rg int i, t = 0, S;
        for (i = 0, S = rhs.c.size (); i < S; ++ i)
            c[i] += rhs.c[i] + t, t = c[i] >= Big_B, c[i] -= Big_B & (-t);
        for (i = rhs.c.size (), S = c.size (); t && i < S; ++ i)
            c[i] += t, t = c[i] >= Big_B, c[i] -= Big_B & (-t);
        if (t) c.push_back (t); return *this;
    }
    inline Int &operator -= (const Int &rhs){
        c.resize (max (c.size (), rhs.c.size ())); rg int i, t = 0, S;
        for (i = 0, S = rhs.c.size (); i < S; ++ i)
            c[i] -= rhs.c[i] + t, t = c[i] < 0, c[i] += Big_B & (-t);
        for (i = rhs.c.size (), S = c.size (); t && i < S; ++ i)
            c[i] -= t, t = c[i] < 0, c[i] += Big_B & (-t);
        CrZ (); return *this;
    }
    inline Int &operator *= (const Int &rhs){
        rg int na = c.size (), i, j, S, ai; 
        c.resize (na + rhs.c.size ()); LL t;
        for (i = na - 1; i >= 0; -- i){
            ai = c[i], t = 0, c[i] = 0;
            for (j = 0, S = rhs.c.size (); j < S; ++ j){
                t += c[i + j] + (LL) ai * rhs.c[j];
                c[i + j] = t % Big_B, t /= Big_B;
            }
            for (j = rhs.c.size (), S = c.size (); t != 0 && i + j < S; ++ j)
                t += c[i + j], c[i + j] = t % Big_B, t /= Big_B;
            assert (t == 0);
        }
        CrZ (); return *this;
    }
    inline Int &operator /= (const Int &rhs) { return *this = div (rhs); }
    inline Int &operator %= (const Int &rhs) { return div (rhs), *this; }
    inline Int &shlb (int l = 1){
        if (c.empty ()) return *this; c.resize (c.size () + l);rg int i;
        for (i = c.size () - 1; i >= l; -- i) c[i] = c[i - l];
        for (i = 0; i < l; ++ i) c[i] = 0;
        return *this;
    }
    inline Int &shrb (int l = 1){
        for (rg int i = 0; i < c.size () - l; ++ i) c[i] = c[i + l];
        c.resize (max (c.size () - l, 0)); return *this;
    }
    inline Int div (const Int &rhs){
        assert (!rhs.c.empty ()); Int q, r; rg int i; if (rhs > *this) return 0;
        q.c.resize (c.size () - rhs.c.size () + 1); rg int _l, _r, mid;
        for (i = c.size () - 1; i > c.size () - rhs.c.size (); -- i) r.shlb (), r += c[i];
        for (i = c.size () - rhs.c.size (); i >= 0; -- i){
            r.shlb (); r += c[i]; 
            if (r.Comp (rhs) < 0) q.c[i] = 0;
            else {
                _l = 0, _r = Big_B;
                for (; _l != _r; ){
                    mid = _l + _r >> 1;
                    if ((rhs * mid).Comp (r) <= 0) _l = mid + 1; else _r = mid;
                }
                q.c[i] = _l - 1, r -= rhs * q.c[i];
            }
        }
        q.CrZ (), *this = r; return q;
    }
    inline int Comp (const Int &rhs) const {
        if (c.size () != rhs.c.size ()) return intcmp_ (c.size (), rhs.c.size ());
        for (rg int i = c.size () - 1; i >= 0; -- i) 
            if (c[i] != rhs.c[i]) return intcmp_ (c[i], rhs.c[i]);
        return 0;
    }
    friend inline Int operator + (const Int &lhs, const Int &rhs)
    { Int res = lhs; return res += rhs; }
    inline friend Int operator - (const Int &lhs, const Int &rhs){ 
        if (lhs < rhs){
            putchar ('-'); 
            Int res = rhs; return res -= lhs;
        }
        else { Int res = lhs; return res -= rhs; }
    }
    friend inline Int operator * (const Int &lhs, const Int &rhs)
    { Int res = lhs; return res *= rhs; }
    friend inline Int operator / (const Int &lhs, const Int &rhs)
    { Int res = lhs; return res.div (rhs); }
    friend inline Int operator % (const Int &lhs, const Int &rhs)
    { Int res = lhs; return res.div (rhs), res; }
    friend inline std :: ostream &operator << (std :: ostream &out, const Int &rhs){ 
        if (rhs.c.size () == 0) out << "0";
        else {
            out << rhs.c.back ();
            for (rg int i = rhs.c.size () - 2; i >= 0; -- i)
                out << std :: setfill ('0') << std :: setw (Big_L) << rhs.c[i];
        }
        return out;
    } 
    friend inline std :: istream &operator >> (std :: istream &in, Int &rhs){
        static char s[100000];
        in >> s + 1; int Len = strlen (s + 1);
        int v = 0; LL r = 0, p = 1;
        for (rg int i = Len; i >= 1; -- i){
            ++ v; r = r + (s[i] - '0') * p, p *= 10;
            if (v == Big_L) rhs.c.push_back (r), r = 0, v = 0, p = 1;
        }
        if (v != 0) rhs.c.push_back (r); return in;
    }
    friend inline bool operator < (const Int &lhs, const Int &rhs)
    { return lhs.Comp (rhs) < 0; }
    friend inline bool operator <= (const Int &lhs, const Int &rhs)
    { return lhs.Comp (rhs) <= 0; }
    friend inline bool operator > (const Int &lhs, const Int &rhs)
    { return lhs.Comp (rhs) > 0; }
    friend inline bool operator >= (const Int &lhs, const Int &rhs)
    { return lhs.Comp (rhs) >= 0; }
    friend inline bool operator == (const Int &lhs, const Int &rhs)
    { return lhs.Comp (rhs) == 0; }
    friend inline bool operator != (const Int &lhs, const Int &rhs)
    { return lhs.Comp (rhs) != 0; }
#undef rg    
};
int Main (){
    return 0;
}
int ZlycerQan = Main ();
int main (int argc, char *argv[]) {;}
高精板子

 

    queue<int>q;
    vector<int>edge[n];
    for(int i=0;i<n;i++)  //n  節點的總數
        if(in[i]==0) q.push(i);  //將入度爲0的點入隊列
    vector<int>ans;   //ans 爲拓撲序列
    while(!q.empty())
    {
        int p=q.front(); q.pop(); // 選一個入度爲0的點,出隊列
        ans.push_back(p);
        for(int i=0;i<edge[p].size();i++)
        {
            int y=edge[p][i];
            in[y]--;
            if(in[y]==0)
                q.push(y);  
        }
    }
    if(ans.size()==n)   
    {
        for(int i=0;i<ans.size();i++)
            printf( "%d ",ans[i] );
        printf("\n");
    }
    else printf("No Answer!\n");  
拓撲排序

 

有關最短路的東西:

//1、多源最短路算法——Floyd 算法
//floyd 算法主要用於求任意兩點間的最短路徑,也稱最短最短路徑問題
//核心代碼:
void floyd() {
    int i, j, k;
    for (k = 1; k <= n; ++k) //遍歷全部的中間點
        for (i = 1; i <= n; ++i) //遍歷全部的起點
            for (j = 1; j <= n; ++j) //遍歷全部的終點
                if (e[i][j] > e[i][k] + e[k][j]) //若是當前i-->j的距離大於i-->k--->j的距離之和
                    e[i][j] = e[i][k] + e[k][j];//更新從i--->j的最短路徑
}
//  時間複雜度:O(N^3)
//  不能使用的狀況:邊中含有負權值



//2、單源最短路徑算法——dijkstra
//一、思想描述:當Q(一開始爲全部節點的集合)非空時,
//不斷地將Q中的最小值u取出,而後放到S(最短路徑的節點的集合)集合中,
//而後遍歷全部與u鄰接的邊,若是能夠進行鬆弛,
//則對便進行相應的鬆弛。。。
//二、實現
/**
 * 返回從v---->到target的最短路徑
 */
int dijkstra(int v) {
    int i;
    for(i = 1 ; i <= n ; ++i) { //初始化
        s[i] = 0;//一開始,全部的點均爲被訪問過
        dis[i] = map[v][i];
    }
    dis[v] = 0;
    s[v] = true;
    for(i = 1 ; i < n ; ++i) {
        int min = inf,pos,j;
        for(j = 1 ; j <= n ; ++j)//尋找目前的最短路徑的最小點
            if(!s[j] && dis[j] < min) {
                min = dis[j];
                pos = j;
            }
        s[pos] = 1;
        for(j = 1 ; j <= n ; j++)//遍歷u的全部的鄰接的邊
            if(!s[j] && dis[j] > dis[pos] + map[pos][j])
                dis[j] = dis[pos] + map[pos][j];//對邊進行鬆弛
    }
    return dis[target];
}
//3.基本結構
int s[maxn];//用來記錄某一點是否被訪問過
int map[maxn][maxn];//地圖
int dis[maxn];//從原點到某一個點的最短距離(一開始是估算距離)
//4.條件:使用dijkstra解決的題目通常有如下的特徵:
//給出點的數目、邊的數目、起點和終點、邊的信息(,而且邊不包含負邊權的值).求從起點到終點的最短路徑的距離
//起點:用於dijkstra(int v)中的v
//終點:用於return dis[target]中的target
//邊的信息:用於初始化map[][]

//三:使用 bellmen-ford 算法
//算法介紹:
//思想:其實bellman-ford的思想和dijkstra的是很像的,
//其關鍵點都在於不斷地對邊進行鬆弛。
//而最大的區別就在於前者能做用於負邊權的狀況。
//其實現思路仍是在求出最短路徑後,
//判斷此刻是否還能對便進行鬆弛,
//若是還能進行鬆弛,便說明還有負邊權的邊
//實現:
bool  bellmen_ford() {
    for(int i=1; i<=n; i++)
        dis[i]=inf;
    dis[source]=0;
    for(int i=1; i<n; i++) {
        for(int j=1; j<=m; j++) {
            dis[edge[j].v] = min(dis[edge[j].v],dis[edge[j].u] + edge[j].weight);
            dis[edge[j].u] =min(dis[edge[j].u],dis[edge[j].v] + edge[j].weight) ;
        }
    }
    for(j = 1 ; j <= m ; ++j)  //判斷是否有負邊權的邊
        if(dis[edge[j].v] > dis[edge[j].u] + edge[j].weight)
            return false;
    return true;
}
//基本結構:
struct Edge{
    int u,v,weight;
}edge[maxn];
int dis[maxn];
//條件:其實求最短路徑的題目的基本條件都是點數,邊數,起點終點


//4、使用spfa算法來解決
//思想:用於求單源最短路經,能夠適用於負邊權的狀況(不過他已經死了 
View Code

 大佬給的網站:Graph Editor

相關文章
相關標籤/搜索