zoukankan      html  css  js  c++  java
  • 板子们

    1.数学

    1.1、(扩展)欧几里得

    void gcd(int a,int b,int &d,int &x,int &y)
    {
        if(!b) { d=a; x=1; y=0; }
        else { gcd(b,a%b,d,y,x);  y-=x*(a/b); }
    }
    View Code

    1.2、同余方程

    //解同余方程 ax≡c(mod b)
    //转化为ax-by=c 
    void solve()
    {
        gcd(a,b,g,x0,y0);  
        if(c%g) printf("no solution");
        x=c/g*x0; y=c/g*y0;
        printf("任意一组解:%d",x);
        a/=g; b/=g;
        x=(x%b+b)%b
        printf("最小x正整数解:%d",x); 
    }
    View Code

    扩展欧几里得、同余方程 解析:http://www.cnblogs.com/TheRoadToTheGold/p/6645383.html

    1.3、快速幂

    int quickmul(int a,int b,int p)
    {
        int ans=1;
        for(;b;b>>=1,a=a*a%p)
         if(b&1) ans=ans*a%p;
        return ans;
    }  
    View Code

    1.4、素数判定

    1.4.1. 费马小定理  若 a、p互质 ,则 a^(p-1) %p=1

    缺陷:Carmichael数可以通过素数判定

    O(次数*log)

    #include<ctime>
    #include<cstdio>
    #include<cstdlib>
    using namespace std;
    typedef long long LL;
    LL p;
    bool flag;
    LL mul(LL a,LL b)
    {
        a%=p; b%=p;
        LL r=0;
        while(b)
        {
            if(b&1) { b--; r=(r+a)%p; }
            a<<=1; a%=p; b>>=1;
        }
        return r;
    }
    LL qm(LL a,LL b)
    {
        LL r=1;
        while(b)
        {
            if(b&1) r=mul(r,a);
            b>>=1; a=mul(a,a);
        }
        return r;
    }
    int main()
    {
        scanf("%lld",&p);
        srand(time(0));
        for(int i=1;i<=15;i++)
        {
            LL a=rand()%(p-1)+1;
            LL x=qm(a,p-1);
            if(x!=1) { flag=1; break; }
        }
        if(flag) printf("No");
        else printf("Yes");
    }
    View Code

    1.4.2 Miller_Rabin

    不会误判Carmichael数,误判概率为1/4^T

    判断四五次大概够了

    #include<ctime>
    #include<cstdio>
    #include<cstdlib>
    using namespace std;
    typedef long long LL;
    LL p;
    LL mul(LL a,LL b)
    {
        LL r=0;
        while(b)
        {
            if(b&1) r+=a,r%=p;
            a<<=1; a%=p; b>>=1;
        }
        return r;
    }
    LL qm(LL a,LL b)
    {
        LL r=1;
        while(b)
        {
            if(b&1) r=mul(r,a);
            a=mul(a,a);  b>>=1;
        }
        return r;
    }
    bool Miller_Rabin()
    {
        if(p==2) return true;
        if(p==1 ||  p%2==0) return false;
        LL x,y,m,k=0,a;
        m=p-1;
        while(m%2==0) k++,m>>=1;
        int T=4;
        while(T--)
        {
            a=rand()%(p-1)+1;
            x=qm(a,m);
            for(int i=1;i<=k;i++)
            {
                y=mul(x,x);
                if(x&1 && y==1 && x!=1 && x!=p-1) return false;
                x=y;
            }
            if(x!=1) return false;
        }
        return true;
    }
    int main()
    {
        srand(time(0));
        scanf("%lld",&p);
        if(Miller_Rabin()) printf("Yes");
        else printf("No");
    }
    View Code

    1.5  素数相关

    1.5.1 素数线性筛

    void solve()
    {
        for(int i=2;i<=N;i++)
        {
            if(!v[i])  prime[++cnt]=i;
            for(int j=1;j<=cnt;j++)
            {
                if(prime[j]*i>=N) break;
                v[prime[j]*i]=true;
                if(i%prime[j]==0) break;
            }
        }
    }
    View Code

    1.5.2 唯一分解定理

    #include<cmath>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    int p[100001],c[100001];
    int main()
    {
        int n,sum;
        while(scanf("%d",&n)!=EOF)
        {
            memset(c,0,sizeof(c));
            sum=0;
            int m=sqrt(n);
            for(int i=2;i<=m;i++)
             if(n%i==0)
             {
                 p[++sum]=i;
                 while(n%i==0) n/=i,c[sum]++;
             }
            if(n>1) p[++sum]=n,c[sum]++;
            for(int i=1;i<=sum;i++) printf("%d %d
    ",p[i],c[i]);
        }
    }
    View Code

    1.5.3 阶乘的质因数分解

    for(int i=1;prime[i]<=n;i++)
    {
        int t=n;
        while(t)
        {
            cnt[i]+=t/prime[i];
            t/=prime[i];
        }
    }
    View Code

    1.6 欧拉函数

    原理 请转至http://www.cnblogs.com/TheRoadToTheGold/p/6598367.html

    1.6.1  欧拉函数计算

    void euler(int n)
    {
        int ans=n;
        for(int i=2;i*i<=n;i++)
         if(n%i==0)
         {
             ans=ans/i*(i-1);
             while(n%i==0) n/=i;
         }
        if(n>1) ans=ans/n*(n-1);
    }
    View Code

    1.6.2 欧拉筛

    O(n)

    void euler_table()
    {
        phi[1]=1;
        for(int i=2;i<=n;i++)
        {
            if(!v[i]) 
            {
                prime[++cnt]=i;
                phi[i]=i-1;
            }
            for(int j=1;j<=cnt;j++)
            {
                if(prime[j]*i>=N) break;
                v[prime[j]*i]=true;
                if(i%prime[j]) phi[prime[j]*i]=phi[i]*(prime[j]-1);
                else
                {
                    phi[prime[j]*i]=prime[j]*phi[i];
                    break;
                }
            }
        }
    }
    View Code

    1.6.3 埃拉托斯特尼筛

    O(nlog²n)

    int eratosthenes(int n)
    {
        int ans=n,k=n;
        int m=sqrt(n);
        for(int i=2;i<=m;i++)
         if(n%i==0)
         {
             ans=ans/i*(i-1);
             for(int j=1;j*i<=k;j++) v[i*j]=false;
             while(n%i==0) n/=i;
         }
        if(n>1)
        {
            ans=ans/n*i;
            for(int j=1;j*i<=k;j++) v[i*j]=false;
        }
        return ans;
    }
    View Code

    1.6.4 杜教筛

    待填坑

    1.7 莫比乌斯函数

    原理转至 http://www.cnblogs.com/TheRoadToTheGold/p/6598088.html

    1.7.1 线性筛 

    void mobius()
    {
        mul[1]=1;
        for(int i=2;i<=n;i++) 
        {
            if(v[i]) 
            {
                prime[++cnt]=i;
                mul[i]=-1;
            }
    
            for(int j=1;j<=cnt;j++) 
            {
                if(i*prime[j]>=N) break;
                v[i*prime[j]]=true;
                if(i%prime[j]==0) { mul[i*prime[j]]=0; break; }
                mul[i*prime[j]]=-mul[i];
            }
        }
    }
    View Code

    1.7.2 杜教筛

    待填坑

    1.8 逆元

    只有 a p 互质,a才有关于p的逆元

    原理请见:http://www.cnblogs.com/linyujun/p/5194184.html

    1.8.1   费马小定理  限制条件:p是质数

    int quickpow(int a,int b,int p)
    {
        int r=1;
        while(b)
        {
            if(b&1) r8=a,r%=p;
            b>>=1; a*=a; a%=p;
        }
        return r;
    }
    void solve(int a,int p)
    {
        if(prime(p)) printf("%d",quickpow(a,p-2,p));
    }
    View Code

    1.8.2    扩展欧几里得

    void exgcd(int a,int b,int& g,int& x,int& y)
    {
        if(!b) { g=a; x=1; y=0; }
        else { exgcd(b,a%b,g,y,x); y-=x*(a/b); }
    }
    void solve()
    {
        exgcd(a,b,g,x,y);
        if(g!=1) return;
        printf("%d",(x%p+p)%p);
    }
    View Code

    1.8.3 递推 限制条件:p是质数

    void solve(int p)
    {
        inv[1]=1;
        for(int i=2;i<N;i++) inv[i]=(p-p/i)*inv[p%i]%p;
    }
    View Code

    1.9 中国剩余定理

    1.9.1 大数翻倍法

    #include<cstdio>
    using namespace std;
    int n,a[11],b[11];
    long long get_gcd(long long a,long long b)
    {
        return !b ? a:get_gcd(b,a%b);
    }
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++) scanf("%d%d",&a[i],&b[i]);
        long long ans=b[1];
        long long lcm=a[1];
        for(int i=2;i<=n;i++)
        {
            while(ans%a[i]!=b[i]) ans+=lcm;
            long long gcd=get_gcd(lcm,(long long)a[i]);
            lcm=lcm/gcd*(long long)a[i];
        }
        printf("%lld",ans);
    }
    View Code

    1.9.2 中国剩余定理 互质版

    #include<cstdio>
    using namespace std;
    int n;
    int m[11],a[11];
    long long M=1,ans,Mi[11],e[11];
    void exgcd(long long a,long long b,long long &x,long long &y)
    {
        if(!b) x=1,y=0;
        else { exgcd(b,a%b,y,x); y-=x*(a/b); }
    }
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++) scanf("%d%d",&m[i],&a[i]),M*=m[i];
        for(int i=1;i<=n;i++) Mi[i]=M/m[i];
        long long x,y;
        for(int i=1;i<=n;i++) 
        {
            exgcd(Mi[i],m[i],x,y);
            x=(x%m[i]+m[i])%m[i];
            e[i]=Mi[i]*x%M;
        }
        for(int i=1;i<=n;i++) ans=(ans+e[i]*a[i])%M;
        printf("%lld",ans);
    }
    View Code

    这两个原理见:http://www.cnblogs.com/TheRoadToTheGold/p/6638430.html

      

    1.9.3 中国剩余定理 非互质版

    待填坑

    1.10 卢卡斯定理

    1.10.1 互质版

    1.10.1.1  预处理阶乘

    #include<cstdio>
    using namespace std;
    typedef long long LL;
    LL f[100001];
    void pre(int p)
    {
        f[0]=1;
        for(int i=1;i<=p;i++) f[i]=f[i-1]*i%p;
    }
    int pow(LL a,int b,int p)
    {
        LL r=1;
        while(b)
        {
            if(b&1) r*=a,r%=p;
            b>>=1; a*=a; a%=p; 
        }
        return r;
    }
    int C(int n,int m,int p)
    {
        if(m>n) return 0; //如果m>n,那么原来的m<n-p,即m与n之间至少有一个p的倍数,那么结果为0 
        return f[n]*pow(f[m]*f[n-m],p-2,p)%p;
    }
    /*int Lucas(int n,int m,int p)
    {
        if(!m) return 1;
        return (C(n%p,m%p,p)*Lucas(n/p,m/p,p))%p;
    }*/
    int Lucas(int n,int m,int p) //非递归版,上面是递归版 
    {
        LL ans=1;
        for(;m;n/=p,m/=p) ans=ans*C(n%p,m%p,p)%p; 
        return ans;
    }
    int main()
    {
        int T,n,m,p;
        scanf("%d",&T);
        while(T--)
        {
            scanf("%d%d%d",&n,&m,&p);
            pre(p);
            printf("%d
    ",Lucas(n,m,p));
        }    
    }
    View Code

    1.10.1.2  阶乘不能预处理

    #include<cstdio>
    using namespace std;
    typedef long long LL;
    /*int pow(LL a,int b,int p)
    {
        LL r=1;
        while(b)
        {
            if(b&1) r*=a,r%=p;
            b>>=1; a*=a; a%=p;
        }
        return r;
    }*/
    void exgcd(int a,int b,LL &x,LL &y)
    {
        if(!b) { x=1; y=0; }
        else { exgcd(b,a%b,y,x); y-=x*(a/b); }
    }
    int inv(int x,int p)
    {
        //return pow(x,p-2,p);
        LL x0,y0;
        exgcd(x,p,x0,y0);
        return (x0%p+p)%p;
    }
    int C(int n,int m,int p)
    {
        if(n<m) return 0;
        LL r=1;
        //for(int i=m+1;i<=n;i++) r=r*i%p*inv(i-m,p)%p;  TLE
        for(int i=1;i<=m;i++) r=r*(n-i+1)%p*inv(i,p)%p;
        return r;
    }
    int Lucas(int n,int m,int p)
    {
        LL ans=1;
        for(;m;n/=p,m/=p) 
        ans=ans*C(n%p,m%p,p)%p;
        return ans;
    }
    int main()
    {
        int n,m,p;
        while(scanf("%d%d%d",&n,&m,&p)!=EOF)
        printf("%d
    ",Lucas(n,m,p));
    }
    View Code

     1.10.2  扩展卢卡斯

     待填坑

    1.11 Catalan数

    #include<cstdio>
    #define mod 100000007
    using namespace std;
    long long f[20000];
    int main()
    {
        int n;
        scanf("%d",&n);
        f[0]=f[1]=1;
        for(int i=2;i<=n;i++)
         for(int j=1;j<=i;j++)
          f[i]=(f[i]+f[j-1]*f[i-j]%mod)%mod;
        //for(int i=2;i<=n;i++) f[i]=f[i-1]*(4*i-2)/(i+1);
        printf("%lld",f[n]);
    }
    View Code

    1.12 矩阵树定理

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    int n,m;
    long long t,C[101][101],ans;
    long long Matrix_tree()
    {
        ans=1;
        for(int i=1;i<n;i++)
        {
            for(int j=i+1;j<n;j++)
            while(C[j][i])
            {
                t=C[i][i]/C[j][i];
                for(int k=i;k<n;k++) C[i][k]-=C[j][k]*t;
                for(int k=i;k<n;k++) swap(C[i][k],C[j][k]);
                ans=-ans;
            }
            if(!C[i][i]) return 0;
            ans*=C[i][i];
        }
        return ans;
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        int u,v;
        while(m--)
        {
            scanf("%d%d",&u,&v);
            u--; v--;
            C[u][v]--; C[v][u]--;
            C[u][u]++; C[v][v]++;
        }
        printf("%lld",Matrix_tree());
    }
    View Code

    2.图论

    2.1 最短路

    2.1.1 Floyd 

      scanf("%d%d",&n,&m);
        memset(f,63,sizeof(f));
        while(m--)
        {
            scanf("%d%d%d",&a,&b,&c);
            f[a][b]=f[b][a]=min(f[a][b],c);
        }
        for(int i=1;i<=n;i++) f[i][i]=0;
        for(int k=1;k<=n;k++)
            for(int i=1;i<=n;i++)
                for(int j=1;j<=n;j++)
                    f[i][j]=min(f[i][j],f[i][k]+f[k][j]);
    View Code

    2.1.2 Dijkstra

    2.1.2.1 普通Dijkstra

    void dijkstra()
    {
            memset(v,false,sizeof(v));
            memset(dis,63,sizeof(dis));
            v[1]=true;
            dis[1]=0;
            int minn,k;
            for(int i=1;i<n;i++)
            {
                k=0;
                minn=0x7fffffff;
                for(int j=1;j<=n;j++) 
                    if(!v[j] && dis[j]<minn ) minn=dis[j],k=j;
                if(!k) break;
                v[k]=true;
                for(int j=1;j<=n;j++)
                    if(dis[j]>dis[k]+e[k][j] ) dis[j]=dis[k]+e[k][j];
            }        
    }        
            
    View Code

    2.1.2.2 堆优化

    #include<cstdio>
    #include<queue>
    #include<cstring>
    #define N 55000
    #define M 1000000
    using namespace std;
    int n,m,s,t,tot;
    int nxt[M],to[M],front[N],cap[M];
    int DIS[N];
    bool vis[N];
    struct edge
    {
        int number,dis;
        bool operator <(edge b) const
        {
            return dis>b.dis;
        }
    }now,nt;
    priority_queue<edge>q;
    void add(int u,int v,int w)
    {
        to[++tot]=v; nxt[tot]=front[u]; front[u]=tot; cap[tot]=w;
        to[++tot]=u; nxt[tot]=front[v]; front[v]=tot; cap[tot]=w;
    }
    bool dijkstra()
    {
        for(int i=1;i<=n;i++) DIS[i]=2e9;
        q.push((edge){s,0});
        DIS[s]=0;
        while(!q.empty())
        {
            now=q.top();q.pop();
            if(vis[now.number]) continue;
            vis[now.number]=true;
            for(int i=front[now.number];i;i=nxt[i])
            {
                if(DIS[to[i]]>DIS[now.number]+cap[i])
                {
                    DIS[to[i]]=DIS[now.number]+cap[i];
                    q.push((edge){to[i],DIS[to[i]]});
                }
            }
        }
        printf("%d",DIS[t]);
    }
    
    int main()
    {
        int u,v,w;
        scanf("%d%d%d%d",&n,&m,&s,&t);
        while(m--)
        {
            scanf("%d%d%d",&u,&v,&w);
            add(u,v,w);
        }
        dijkstra();
    }
    View Code

    2.1.3 spfa

    void spfa()
    {
        memset(dis,63,sizeof(dis));
        dis[1]=0; q.push(1); vis[1]=true;
        int now;
        while(!q.empty())
        {
            now=q.front(); q.pop(); vis[now]=false;
            for(int i=front[now];i;i=nxt[i])
                if(dis[to[i]]>dis[now]+val[i])
                {
                    dis[to[i]]=dis[now]+val[i];
                    if(!vis[to[i]]) vis[to[i]]=true,q.push(to[i]);
                }
        }
    }
    View Code

    2.2 次短路

    注:代码是严格的次短路

    #include<queue>
    #include<cstdio>
    #include<cstring>
    #define N 5001
    #define M 100001
    using namespace std;
    int front[N],to[M<<1],nxt[M<<1],val[M<<1],from[M<<1],tot;
    int dis1[N],dis2[N];
    bool vis[N];
    queue<int>q;
    void add(int u,int v,int w)
    {
        to[++tot]=v; nxt[tot]=front[u]; front[u]=tot; val[tot]=w; from[tot]=u;
        to[++tot]=u; nxt[tot]=front[v]; front[v]=tot; val[tot]=w; from[tot]=v;
    }
    void spfa(int s,int *dis)
    {
        //memset(dis,63,sizeof(dis));
        memset(vis,false,sizeof(vis));
        q.push(s);
        vis[s]=true;
        dis[s]=0;
        int now;
        while(!q.empty())
        {
            now=q.front();
            q.pop();
            vis[now]=false;
            for(int i=front[now];i;i=nxt[i])
                if(dis[to[i]]>dis[now]+val[i])
                {
                    dis[to[i]]=dis[now]+val[i];
                    if(!vis[to[i]])
                    {
                        vis[to[i]]=true;
                        q.push(to[i]);
                    }
                }
        }
    }
    int main()
    {
        int n,m;
        scanf("%d%d",&n,&m);
        int u,v,w;
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d%d",&u,&v,&w);
            add(u,v,w);
        }
        memset(dis1,63,sizeof(dis1));
        memset(dis2,63,sizeof(dis2));
        spfa(1,dis1);
        spfa(n,dis2);
        int minn=dis1[n],tmp,ans=0x7fffffff;
        for(int i=1;i<=tot;i++)
        {
            u=from[i]; v=to[i];
            tmp=dis1[u]+val[i]+dis2[v];
            if(tmp>minn && tmp<ans) ans=tmp;
        }
        printf("%d",ans);
    }
    View Code

    2.3 k短路

    注:代码是不严格的k短路

    http://www.cnblogs.com/TheRoadToTheGold/p/7416264.html

    #include<queue>
    #include<cstdio>
    #include<cstring>
    #define N 1001
    #define M 100001
    using namespace std;
    int n,s,t,k;
    int dis1[N];
    bool vis[N];
    int front[N],to[M],nxt[M],val[M],tot;
    int front2[N],to2[M],nxt2[M],val2[M],tot2;
    struct node
    {
        int num,dis;
        bool operator < (node p) const
        {
            return dis+dis1[num]>p.dis+dis1[p.num];
        } 
    }now,nt;
    void add(int u,int v,int w)
    {
        to[++tot]=v; nxt[tot]=front[u]; front[u]=tot; val[tot]=w;
        to2[++tot2]=u; nxt2[tot2]=front2[v]; front2[v]=tot2; val2[tot2]=w; 
    }
    void init()
    {
        int m,u,v,w;
        scanf("%d%d",&n,&m);
        while(m--)
        {
            scanf("%d%d%d",&u,&v,&w);
            add(u,v,w);
        }
        scanf("%d%d%d",&s,&t,&k);
    }
    void spfa()
    {
        memset(dis1,63,sizeof(dis1));
        queue<int>q;
        dis1[t]=0;
        vis[t]=true;
        q.push(t);
        int now;
        while(!q.empty())
        {
            now=q.front();
            q.pop();
            vis[now]=false;
            for(int i=front2[now];i;i=nxt2[i])
                if(dis1[to2[i]]>dis1[now]+val2[i])
                {
                    dis1[to2[i]]=dis1[now]+val2[i];
                    if(!vis[to2[i]])
                    {
                        q.push(to2[i]);
                        vis[to2[i]]=true;
                    }
                }
        }
    }
    void Astar()
    {
        if(dis1[s]>1e9) 
        {
            printf("-1");
            return;
        }    
        if(s==t) k++;
        int cnt=0,last=-1;
        priority_queue<node>q;
        now.num=s;
        now.dis=0;
        q.push(now);
        while(!q.empty())
        {
            now=q.top();
            q.pop();
            if(now.num==t) 
            {
                cnt++;
                if(cnt==k) 
                {
                    printf("%d",now.dis);
                    return;
                }
            }
            for(int i=front[now.num];i;i=nxt[i])
            {
                nt.num=to[i];
                nt.dis=now.dis+val[i];
                q.push(nt);
            }
        }
        printf("-1");
    }
    int main()
    {
        init();
        spfa();
        Astar();
    }
    View Code

    2.4 最小生成树

    2.4.1 prim

    #include<cstdio>
    #include<cstring>
    using namespace std;
    int a[501][501],minn[501];
    bool vis[501];
    int main()
    {
        int n,m;
        scanf("%d%d",&n,&m);
        int u,v,w;
        memset(a,63,sizeof(a));
        while(m--)
        {
            scanf("%d%d%d",&u,&v,&w);
            if(w<a[u][v]) a[u][v]=a[v][u]=w;
        }
        memset(minn,63,sizeof(minn));
        minn[1]=0;
        int tmp,k,ans=0;
        for(int i=1;i<=n;i++)
        {
            tmp=2e9;
            for(int j=1;j<=n;j++) 
                if(!vis[j] && minn[j]<tmp) 
                {
                    tmp=minn[j];
                    k=j;
                }
            ans+=minn[k];
            vis[k]=true;
            for(int j=1;j<=n;j++)
                if(!vis[j] && a[k][j]<minn[j]) minn[j]=a[k][j];
        }
        printf("%d",ans);
    }
    View Code

    2.4.2 Kruskal

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    int fa[5001];
    struct node
    {
        int u,v,w;
    }e[200001];
    bool cmp(node p,node q)
    {
        return p.w<q.w;
    }
    int find(int i) { return fa[i]==i ? i : fa[i]=find(fa[i]); }
    int main()
    {
        int n,m;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++) scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
        sort(e+1,e+m+1,cmp);
        for(int i=1;i<=n;i++) fa[i]=i;
        int tot=0;
        int r1,r2,i=1,ans=0;
        while(tot<n-1)
        {
            r1=find(e[i].u);
            r2=find(e[i].v);
            if(r1!=r2) 
            {
                fa[r1]=r2;
                ans+=e[i].w;
                tot++;
            }
            i++; 
        }
        printf("%d",ans);
    }
    View Code

    2.5 最小树形图

    #include<cstdio>
    #include<cstring>
    #define N 1005
    #define M 10005
    #define inf 2e9
    using namespace std;
    struct node
    {
        int u,v,w;
    }e[M];
    int in[N],pre[N],vis[N],col[N],id[N];
    int n,m;
    int directed_MST()
    {
        int tot=n+1,root=0,ans=0,cirnum=0,to;
        while(1)
        {
            for(int i=0;i<tot;i++) in[i]=inf; 
            for(int i=1;i<=m;i++)
                if(e[i].u!=e[i].v && in[e[i].v]>e[i].w) 
                {
                    in[e[i].v]=e[i].w;
                    pre[e[i].v]=e[i].u;
                }
            cirnum=0;
            memset(vis,-1,sizeof(vis));
            memset(col,-1,sizeof(col));
            in[root]=0;
            for(int i=0;i<tot;i++)
            {
                ans+=in[i];
                to=i;
                while(vis[to]!=i && col[to]==-1 && to!=root)
                {
                    vis[to]=i;
                    to=pre[to];
                }
                if(to!=root && col[to]==-1)
                {
                    for(int nt=pre[to];nt!=to;nt=pre[nt])
                        col[nt]=cirnum;
                    col[to]=cirnum++;
                }
            }
            if(!cirnum) return ans;
            for(int i=0;i<tot;i++) 
                if(col[i]==-1) col[i]=cirnum++;
            for(int i=1;i<=m;i++)
            {
                to=e[i].v;
                e[i].u=col[e[i].u];
                e[i].v=col[e[i].v];
                if(e[i].u!=e[i].v) e[i].w-=in[to];
            }
            tot=cirnum;
            root=col[root];
        }
        return ans;
    }
    int main()
    {
        int tot;
        int u,v,w,ans;
        while(scanf("%d%d",&n,&m)!=EOF)
        {
            tot=0;
            while(m--)
            {
                scanf("%d%d%d",&u,&v,&w);
                if(u!=v)
                {
                    u++; v++;
                    e[++tot].u=u; e[tot].v=v; e[tot].w=w;
                }
            }
            m=tot;
            ans=directed_MST();
            printf("%d",ans);
        }
    }
    View Code
  • 相关阅读:
    轻松搭建Redis缓存高可用集群
    Redis集群主从配置
    启动Redis Cluster
    MyISAM 和 InnoDB 索引的区别
    数据库面试
    如何定位php程序访问慢
    Socket技术详解
    NGINX快速入门
    nginx 并发数问题思考:worker_connections,worker_processes与 max clients
    php-fpm运行原理
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/7323273.html
Copyright © 2011-2022 走看看