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
原文地址:https://www.cnblogs.com/AKCqhzdy/p/9518685.html