分层图

分层图

分层图的两种写法

P4568 [JLOI2011] 飞行路线

1.建立实际的多层图(直接跑裸的dij就行)

per(i,1,m)
{
    scanf("%d%d%d",&x,&y,&po);
    ++x,++y;
    add(x,y,po);
    add(y,x,po);
    per(j,1,k)
    {
    add(x+(j-1)*n,y+j*n);
    add(y+(j-1)*n,x+j*n);
    add(x+j*n,y+j*n,po);
    add(y+j*n,x+j*n,po);
    }
}

代码:

#include <bits/stdc++.h>
using namespace std;
#define per(i,a,b) for(int i(a);i<=b;++i)
const int N=1e5+1e4+20,M=2500010;
int to[M],hd[N],nx[M],v[M],id;
void add(int x,int y,int c=0)
{
    to[++id]=y,nx[id]=hd[x],v[id]=c;
    hd[x]=id;
}
int d[N];
bool ck[N];
priority_queue<pair<int,int>>q;
void dij(int x)
{
    memset(d,0x3f,sizeof(d));
    d[x]=0;
    q.emplace(0,x);
    while(!q.empty())
    {
        x=q.top().second,q.pop();
        if(ck[x]) continue;
        ck[x]=1;
        for(int i=hd[x];i;i=nx[i])
        {
            if(d[to[i]]>d[x]+v[i])
            {
                d[to[i]]=d[x]+v[i];
                q.emplace(-d[to[i]],to[i]);
            }
        }
    }
}
int main()
{
    int n,m,k,s,t,x,y,po;
    cin>>n>>m>>k>>s>>t;
    ++s,++t;
    per(i,1,m)
    {
        scanf("%d%d%d",&x,&y,&po);
        ++x,++y;
        add(x,y,po);
        add(y,x,po);
        per(j,1,k)
        {
            add(x+(j-1)*n,y+j*n);
            add(y+(j-1)*n,x+j*n);
            add(x+j*n,y+j*n,po);
            add(y+j*n,x+j*n,po);
        }
    }
    per(i,1,k)
    {
        add(t+(i-1)*n,t+i*n);
    }
    dij(s);
    printf("%d\n",d[t+k*n]);
    return 0;
}

2.引入dp思想进行分层松弛(不用建立很多层点)

for(int i=hd[x];i;i=nx[i])
{
	if((c<k)&&!ck[to[i]][c+1]&&d[to[i]][c+1]>d[x][c])
	{
  		d[to[i]][c+1]=d[x][c];
  		q.emplace((aaa){to[i],d[to[i]][c+1],c+1});
  	}
  	if(!ck[to[i]][c]&&d[to[i]][c]>d[x][c]+v[i])
  	{
  		d[to[i]][c]=d[x][c]+v[i];
  		q.emplace((aaa){to[i],d[to[i]][c],c});
 	}
}

代码:

#include <bits/stdc++.h>
using namespace std;
#define per(i,a,b) for(int i(a);i<=b;++i)
const int N=1e4+10,M=1e5+10;
int to[M],nx[M],hd[N],v[M],id;
int n,m,k,s,t;
int d[N][15];
bool ck[N][15];
struct aaa{
    int x,po,t;
    bool operator <(const aaa e) const{
        return po>e.po;
    }
}w;
priority_queue<aaa>q;
void add(int x,int y,int po)
{
    to[++id]=y,nx[id]=hd[x],v[id]=po;
    hd[x]=id;
}
void dij()
{
    int x,c;
    memset(d,0x3f,sizeof(d));
    d[s][0]=0;
    q.emplace((aaa){s,0,0});
    while(!q.empty())
    {
        w=q.top(),q.pop();
        x=w.x,c=w.t;
        // if(ck[x][c]) continue;
        ck[x][c]=1;
        for(int i=hd[x];i;i=nx[i])
        {
            if((c<k)&&!ck[to[i]][c+1]&&d[to[i]][c+1]>d[x][c])
            {
                d[to[i]][c+1]=d[x][c];
                q.emplace((aaa){to[i],d[to[i]][c+1],c+1});
            }
            if(!ck[to[i]][c]&&d[to[i]][c]>d[x][c]+v[i])
            {
                d[to[i]][c]=d[x][c]+v[i];
                q.emplace((aaa){to[i],d[to[i]][c],c});
            }
        }
    }
}
int main()
{
    int x,y,po,ans=INT_MAX;
    cin>>n>>m>>k>>s>>t;
    ++s,++t;
    per(i,1,m)
    {
        scanf("%d%d%d",&x,&y,&po);
        ++x,++y;
        add(x,y,po),add(y,x,po);
    }
    dij();
    per(i,0,k)
    {
        ans=min(ans,d[t][i]);
        // printf("%d\n",d[t][i]);
    }
    printf("%d\n",ans);
    return 0;
}

posted @ 2022-09-22 22:31  f2021yjm  阅读(14)  评论(0编辑  收藏  举报