分层图

分层图

模板

直接看一道裸题

Illegal Motor

分层图_第1张图片


分层图的典型应用,有K条免费边,除了原图外再建K层图。然后对于从每个点出的每一条边,连一条从此点到这条边终点所对应的上一层的点,边权为零,从一层到下一层相当于走了一条免费边。由于不需要走完所有的免费边,所以应取所有层的终点的最短路的最小值。

注意:存图的时候不要开小了,由于还要连跨层边,所以MAXN*(MAXK+1)是远远不够的

如图所示:
这里只画出来0号节点的免费边
分层图_第2张图片


#include
#include
#include
#include
using namespace std;

const int MAXN=1e4,MAXM=5e4,MAXK=10,INF=~0U>>1;
int N,M,K;
int S,T;

struct E{int to,next,value;} e[4*MAXM*(MAXK+1)+MAXK+1];int ecnt,G[MAXN*(MAXK+1)+1];
void addEdge(int u,int v,int w){e[++ecnt]={v,G[u],w};G[u]=ecnt;}

void readInt(int & x)
{
    x=0;
    bool flag=false;
    char c;
    do c=getchar(); while(c!='-'&&(c<'0'||c>'9'));
    if(c=='-') flag=true;
    else x+=c-'0';
    c=getchar();
    while(c>='0'&&c<='9')
    {
        x*=10;
        x+=c-'0';
        c=getchar();
    }
}

inline void read()
{
    int i,j;
    readInt(N);readInt(M);readInt(K);
    readInt(S);readInt(T);
    for(i=1;i<=M;i++)
    {
        int u,v,w;
        readInt(u);readInt(v);readInt(w);
        for(j=0;j<=K;j++)
        {
            addEdge(u+N*j,v+N*j,w);
            addEdge(v+N*j,u+N*j,w);
            if(j!=K)
            {
                addEdge(u+N*j,v+N*(j+1),0);
                addEdge(v+N*j,u+N*(j+1),0);
            }
        }
    }
}

struct HN{int id,v;bool operator<(const HN & ot)const{return v>ot.v;}};

priority_queue heap;

bool inS[MAXN*(MAXK+1)+1];
int dis[MAXN*(MAXK+1)+1];

void dijkstra(int v0)
{
    int i;
    for(i=1;i<=N*(K+1);i++) dis[i]=INF;
    memset(inS,false,sizeof(inS));
    dis[v0]=0;
    heap.push((HN){v0,0});
    while(!heap.empty())
    {
        int u=heap.top().id;heap.pop();
        if(inS[u]) continue;
        inS[u]=true;
        for(i=G[u];i;i=e[i].next)
        {
            int v=e[i].to;
            if(!inS[v])
                if(dis[v]>dis[u]+e[i].value)
                {
                    dis[v]=dis[u]+e[i].value;
                    heap.push((HN){v,dis[v]});
                }
        }
    }
}

int main()
{
    freopen("Motor.in","r",stdin);
    freopen("Motor.out","w",stdout);
    int i;
    read();
    dijkstra(S);
    int ans=INF;
    for(i=0;i<=K;i++) ans=min(ans,dis[T+N*i]);
    printf("%d",ans);
    return 0;
}

你可能感兴趣的:(题解,-联赛)