zoukankan      html  css  js  c++  java
  • 0x61 最短路

    终于会dij了原来我以前写的也是堆优化spfa-_-!

    poj3662DP 通过spfa来放缩(可怜我去年NOIP的day1t3啊)

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    
    struct node
    {
        int x,y,d,next;
    }a[21000];int len,last[1100];
    void ins(int x,int y,int d)
    {
        len++;
        a[len].x=x;a[len].y=y;a[len].d=d;
        a[len].next=last[x];last[x]=len;
    }
    
    int list[1100];
    int f[1100][1100];bool v[1100];
    int main()
    {
        int n,m,K,x,y,d;
        scanf("%d%d%d",&n,&m,&K);
        len=0;memset(last,0,sizeof(last));
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d%d",&x,&y,&d);
            ins(x,y,d);ins(y,x,d);
        }
        
        int head=1,tail=2;list[1]=1;
        memset(f,63,sizeof(f));f[1][0]=0;
        memset(v,false,sizeof(v));v[1]=true;
        while(head!=tail)
        {
            int x=list[head];
            for(int k=last[x];k;k=a[k].next)
            {
                int y=a[k].y;
                for(int p=0;p<=K;p++)
                {
                    int tt=f[y][p];
                    if(p!=0)f[y][p]=min(f[y][p],f[x][p-1]);
                    f[y][p]=min(f[y][p],max(f[x][p],a[k].d));
                    
                    if(tt!=f[y][p]&&v[y]==false)
                    {
                        v[y]=true;
                        list[tail]=y;
                        tail++;if(tail==1050)tail=1;
                    }
                }
            }
            v[x]=false;
            head++;if(head==1050)head=1;
        }
        if(f[n][K]==f[0][0])printf("-1
    ");
        else printf("%d
    ",f[n][K]);
        return 0;
    }
    poj3662

    最优贸易 正反dij分别求最小和最大,然后mx[x]-mn[x]就好(怎么这个专题净勾起我的伤心事啊,初一的某模拟赛就是没还原v数组100变没分啊啊啊)

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    #include<queue>
    using namespace std;
    
    struct node{int x,y,next;}a[1100000],e[1100000];
    int alen,elen,alast[110000],elast[110000];
    void ains(int x,int y)
    {
        alen++;
        a[alen].x=x;a[alen].y=y;
        a[alen].next=alast[x];alast[x]=alen;
    }
    void eins(int x,int y)
    {
        elen++;
        e[elen].x=x;e[elen].y=y;
        e[elen].next=elast[x];elast[x]=elen;
    }
    
    struct dij
    {
        int k,id;
        dij(){}
        dij(int K,int ID){k=K;id=ID;}
        friend bool operator>(dij d1,dij d2){return d1.k>d2.k;}
        friend bool operator<(dij d1,dij d2){return d1.k<d2.k;}
    }; 
    priority_queue<dij,vector<dij>,greater<dij> >aq;
    priority_queue<dij>eq;
    int mn[110000],mx[110000];bool v[110000],inq[110000];
    
    int w[110000];
    int main()
    {
        int n,m,x,y,op;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)scanf("%d",&w[i]);
        alen=0;memset(alast,0,sizeof(alast));
        elen=0;memset(elast,0,sizeof(elast));
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d%d",&x,&y,&op);
            if(op==1)
                ains(x,y), eins(y,x);
            else
                ains(x,y),ains(y,x), eins(x,y),eins(y,x);
        }
        
        memset(v,false,sizeof(v));
        memset(inq,false,sizeof(inq));inq[1]=true;
        mn[1]=w[1]; aq.push(dij(w[1],1));
        while(!aq.empty())
        {
            dij tno=aq.top();aq.pop();
            if(v[tno.id]==true)continue;
            v[tno.id]=true;
            
            int x=tno.id;
            for(int k=alast[x];k;k=a[k].next)
            {
                int y=a[k].y;
                if(inq[y]==false)
                    inq[y]=true, mn[y]=w[y], aq.push(dij(mn[y],y));
                if(mn[y]>tno.k)
                {
                    mn[y]=tno.k;
                    aq.push(dij(mn[y],y));
                }
            }
        }
        
        memset(v,false,sizeof(v));
        memset(inq,false,sizeof(inq));inq[1]=true;
        mx[n]=w[n], eq.push(dij(w[n],n));
        while(!eq.empty())
        {
            dij tno=eq.top();eq.pop();
            if(v[tno.id]==true)continue;
            v[tno.id]=true;
            
            int x=tno.id;
            for(int k=elast[x];k;k=e[k].next)
            {
                int y=e[k].y;
                if(inq[y]==false)
                    inq[y]=true, mx[y]=w[y], eq.push(dij(mx[y],y));
                if(mx[y]<tno.k)
                {
                    mx[y]=tno.k;
                    eq.push(dij(mx[y],y));
                }
            }
        }
        
        int ans=0;
        for(int i=1;i<=n;i++)
            ans=max(ans,mx[i]-mn[i]);
        printf("%d
    ",ans);
        /*
        for(int i=1;i<=n;i++)printf("%d ",mx[i]);
        printf("
    ");
        for(int i=1;i<=n;i++)printf("%d ",mn[i]);
        printf("
    ");*/
        return 0;
    }
    最优贸易

    bzoj2200 这题卡spfa(然而用酸辣粉和啦(fan)啦(you)啦(hua)这两个玄学优化可以过)

    正解呢是topsort+dij,因为把正边看成联通块,负边其实构成的是一个DAG图,所以拓扑排序时顺便把环dij一次

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    #include<queue>
    using namespace std;
    
    struct node
    {
        int x,y,d,next;
    }a[110000];int len,last[31000];
    void ins(int x,int y,int d)
    {
        len++;
        a[len].x=x;a[len].y=y;a[len].d=d;
        a[len].next=last[x];last[x]=len;
    }
    int fa[31000];
    int findfa(int x)
    {
        if(fa[x]==x)return x;
        fa[x]=findfa(fa[x]);return fa[x];
    }
    
    int d[31000];
    struct dij
    {
        int k,id;
        dij(){}
        dij(int K,int ID){k=K;id=ID;}
        friend bool operator>(dij d1,dij d2){return d1.k>d2.k;}
        friend bool operator<(dij d1,dij d2){return d1.k<d2.k;}
    }; bool v[31000];
    priority_queue<dij,vector<dij>,greater<dij> >q;
    void dijkstra(int st,int k)
    {
        if(d[st]<=k)return ;
        d[st]=k;q.push(dij(d[st],st));
        memset(v,false,sizeof(v));
        while(!q.empty())
        {
            dij tno=q.top();q.pop();
            if(v[tno.id]==true)continue;
            v[tno.id]=true;
            
            int x=tno.id;
            for(int k=last[x];k;k=a[k].next)
            {
                int y=a[k].y;
                if(d[y]>d[x]+a[k].d)
                {
                    d[y]=d[x]+a[k].d;
                    q.push(dij(d[y],y));
                }
            }
        }
    }
    
    //----------------合并成联通块+dijkstra处理正环---------------------
    
    struct enode
    {
        int fx,fy,x,y,d,next;
    }e[110000];int elen,elast[31000];
    void eins(int fx,int fy,int x,int y,int d)
    {
        elen++;
        e[elen].fx=fx;e[elen].fy=fy;
        e[elen].x=x;e[elen].y=y;e[elen].d=d;
        e[elen].next=elast[fx];elast[fx]=elen;
    }
    int du[31000],n,S;
    int top,sta[31000];
    void topsort()
    { 
        top=0;sta[++top]=0;
        eins(0,findfa(S),0,S,0),du[findfa(S)]++;
        for(int i=1;i<=n;i++)
            if(findfa(i)==i&&du[i]==0&&i!=findfa(S))
                sta[++top]=i;
        while(top!=1)
        {
            int fx=sta[top];top--;
            for(int k=elast[fx];k;k=e[k].next)
            {
                du[e[k].fy]--;
                if(du[e[k].fy]==0)sta[++top]=e[k].fy;
            }
        }
        while(top!=0)
        {
            int fx=sta[top];top--;
            for(int k=elast[fx];k;k=e[k].next)
            {
                dijkstra(e[k].y,d[e[k].x]+e[k].d);
                du[e[k].fy]--;
                if(du[e[k].fy]==0)sta[++top]=e[k].fy;
            }
        }
    }
    
    //--------------topsort-------------------- 
    
    int main()
    {
        int R,P,x,y,dd;
        scanf("%d%d%d%d",&n,&R,&P,&S);
        len=0;memset(last,0,sizeof(last));
        for(int i=1;i<=n;i++)fa[i]=i;
        for(int i=1;i<=R;i++)
        {
            scanf("%d%d%d",&x,&y,&dd);
            ins(x,y,dd);ins(y,x,dd);
            
            int fx=findfa(x),fy=findfa(y);
            fa[fx]=fy;
        }
        
        memset(du,0,sizeof(du));
        for(int i=1;i<=P;i++)
        {
            scanf("%d%d%d",&x,&y,&dd);
            int fx=findfa(x),fy=findfa(y);
            eins(fx,fy,x,y,dd);
            du[fy]++;
        }
        memset(d,63,sizeof(d));d[0]=0;
        topsort();
        
        for(int i=1;i<=n;i++)
            if(d[i]==d[n+1])printf("NO PATH
    ");
            else printf("%d
    ",d[i]);
        return 0;
    }
    bzoj2200

    poj1734 floyd求最小环,考虑对于一个环,把它拆分成前k-1个点和第k个点,当floyd完k-1次,得到的就是利用前k-1个点相互到达的最短路,此时再加上第k个点构成环,保证不重复,同时,取最大的点和取其他点,效果是一样的。

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    
    int a[110][110],mp[110][110];
    int len,as[110],pos[110][110];
    void getpath(int i,int j)
    {
        if(pos[i][j]==0)return ;
        getpath(i,pos[i][j]);
        as[++len]=pos[i][j];
        getpath(pos[i][j],j);
    }
    
    int main()
    {
        freopen("TRIP.in","r",stdin);
        freopen("TRIP.out","w",stdout);
        int n,m,x,y,d;
        scanf("%d%d",&n,&m);
        memset(mp,63,sizeof(mp));
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d%d",&x,&y,&d);
            mp[x][y]=min(mp[x][y],d);
            mp[y][x]=min(mp[y][x],d);
        }
        memcpy(a,mp,sizeof(mp));
        
        int ans=mp[0][0];
        memset(pos,0,sizeof(pos));
        for(int k=1;k<=n;k++)
        {
            for(int i=1;i<k;i++)
                for(int j=i+1;j<k;j++)
                {
                    if((long long)mp[i][j]+a[i][k]+a[k][j]<ans)
                    {
                        ans=mp[i][j]+a[i][k]+a[k][j];
                        len=0;
                        as[++len]=i;
                        getpath(i,j);
                        as[++len]=j;
                        as[++len]=k;
                    }
                }
                
            for(int i=1;i<=n;i++) if(i!=k)
                for(int j=1;j<=n;j++) if(j!=k&&j!=i)
                    if(mp[i][j]>mp[i][k]+mp[k][j])
                    {
                        mp[i][j]=mp[i][k]+mp[k][j];
                        pos[i][j]=k;
                    }
        }
        if(ans==mp[0][0])printf("No solution.
    ");
        else
        {
            for(int i=1;i<len;i++)printf("%d ",as[i]);
            printf("%d
    ",as[len]);
        }
    
        return 0;
    }
    poj1734

    poj3613 神仙题

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    
    struct line{int d,x,y;}li[110];
    int n,ls[210];
    struct Matrix{int mp[110][110];}A,ans;
    Matrix calc(Matrix a,Matrix b)
    {
        Matrix c;
        memset(c.mp,63,sizeof(c.mp));
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                for(int k=1;k<=n;k++)
                    c.mp[i][j]=min(c.mp[i][j],a.mp[i][k]+b.mp[k][j]);
        return c;
    }
    int main()
    {
        int m,P,S,E;
        scanf("%d%d%d%d",&P,&m,&S,&E);
        n=0;
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d%d",&li[i].d,&li[i].x,&li[i].y);
            ls[++n]=li[i].x;
            ls[++n]=li[i].y;
        }
        sort(ls+1,ls+n+1);
        n=unique(ls+1,ls+n+1)-ls-1;
        for(int i=1;i<=m;i++)
        {
            li[i].x=lower_bound(ls+1,ls+n+1,li[i].x)-ls;
            li[i].y=lower_bound(ls+1,ls+n+1,li[i].y)-ls;
        }
        S=lower_bound(ls+1,ls+n+1,S)-ls;
        E=lower_bound(ls+1,ls+n+1,E)-ls;
        //LSH
        
        memset(A.mp,63,sizeof(A.mp));
        for(int i=1;i<=m;i++)
        {
            int x=li[i].x,y=li[i].y;
            A.mp[x][y]=min(A.mp[x][y],li[i].d);
            A.mp[y][x]=min(A.mp[y][x],li[i].d);
        }
        memcpy(ans.mp,A.mp,sizeof(A.mp));
        P--;
        while(P!=0)
        {
             if(P%2==1)ans=calc(ans,A);
            A=calc(A,A);P/=2;
        }
        printf("%d
    ",ans.mp[S][E]);
        return 0;
    }
    poj3613
  • 相关阅读:
    Code Forces Gym 100886J Sockets(二分)
    CSU 1092 Barricade
    CodeChef Mahesh and his lost array
    CodeChef Gcd Queries
    CodeChef GCD2
    CodeChef Sereja and LCM(矩阵快速幂)
    CodeChef Sereja and GCD
    CodeChef Little Elephant and Balance
    CodeChef Count Substrings
    hdu 4001 To Miss Our Children Time( sort + DP )
  • 原文地址:https://www.cnblogs.com/AKCqhzdy/p/9518685.html
Copyright © 2011-2022 走看看