ACM-ICPC 2018 南京赛区网络预赛 L && BZOJ 2763 分层最短路

https://nanti.jisuanke.com/t/31001

题意 可以把k条边的权值变为0,求s到t的最短路

解析  分层最短路  我们建立k+1层图 层与层之间边权为0,i 向 i+1层转移,代表用了一条免费边。

#include <bits/stdc++.h>
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define all(a) (a).begin(), (a).end()
#define fillchar(a, x) memset(a, x, sizeof(a))
#define huan printf("
");
#define debug(a,b) cout<<a<<" "<<b<<" ";
using namespace std;
const int maxn=3e6+10,inf=0x3f3f3f3f;
typedef long long ll;
typedef pair<int,int> pii;
int n,m,k,st,ed,cnt,head[maxn],vis[maxn];
ll dis[maxn];
struct node
{
    ll from,to,val,next;
} edge[maxn<<1];
struct element
{
    ll val,now;
};
bool operator < (element a,element b)
{
    if(a.val==b.val)
        return a.now<b.now;
    return a.val>b.val;
}
void dijikstra(int s,int e)
{
    priority_queue<element>q;
    memset(dis,0x3f,sizeof(dis));
    dis[s]=0;
    q.push(element{0,s});
    while(!q.empty())
    {
        element u=q.top();
        q.pop();
        if(vis[u.now])
            continue;
        vis[u.now]=1;
        for(int i=head[u.now]; i!=-1; i=edge[i].next)
        {
            int to=edge[i].to;
            if(dis[u.now]+edge[i].val<dis[to])
            {
                dis[to]=dis[u.now]+edge[i].val;
                q.push(element{dis[to],to});
            }
        }
    }
    ll ans=1e18;
    for(int i=0; i<=k; i++)
    {
        if(ans>dis[e+i*n])
            ans=dis[e+i*n];
    }
    printf("%lld
",ans);
}
void init()
{
    memset(head,-1,sizeof(head));
    memset(vis,0,sizeof(vis));
    cnt=1;
}
void edgeadd(ll from,ll to,ll val)
{
    edge[cnt].from=from;
    edge[cnt].to=to;
    edge[cnt].val=val;
    edge[cnt].next=head[from];
    head[from]=cnt++;
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        init();
        scanf("%d%d%d",&n,&m,&k);
        st=1,ed=n;
        for(int i=1; i<=m; i++)
        {
            ll x,y,z;
            scanf("%lld%lld%lld",&x,&y,&z);
            for(int i=0; i<=k; i++)   //分为k+1层图,
            {
                edgeadd(x+i*n,y+i*n,z);  //每层图之间建边
                if(i!=k)
                {
                    edgeadd(x+i*n,y+(i+1)*n,0);//第层i向i+1层图建边 边权为0;
                }
            }
        }
        dijikstra(st,ed);
    }
}

BZOJ 2763

dp思想

/**************************************************************
    Problem: 2763
    User: 1071532391
    Language: C++
    Result: Accepted
    Time:7452 ms
    Memory:6972 kb
****************************************************************/
 
#include <bits/stdc++.h>
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define all(a) (a).begin(), (a).end()
#define fillchar(a, x) memset(a, x, sizeof(a))
#define huan printf("
");
#define debug(a,b) cout<<a<<" "<<b<<" ";
using namespace std;
const int maxn=2e4+10,inf=0x3f3f3f3f;
typedef long long ll;
typedef pair<int,int> pii;
struct edge
{
    int u,v,w,next;
}e[maxn*10];
struct node
{
    int x,y;
};
int cnt,dis[maxn][15],head[maxn],vis[maxn][15];
int n,m,k,s,t;
void init()
{
    cnt=0;
    fillchar(head,-1);
    fillchar(vis,0);
}
void addedge(int u,int v,int w)
{
    e[++cnt].next=head[u];
    e[cnt].u=u;
    e[cnt].v=v;
    e[cnt].w=w;
    head[u]=cnt;
}
void spfa()
{
    fillchar(dis,0x3f);
    queue<node> q;
    q.push(node{s,k});
    dis[s][k]=0;
    while(!q.empty())
    {
        int u=q.front().x;
        int t=q.front().y;
        q.pop();
        vis[u][t]=0;
        for(int i=head[u];i!=-1;i=e[i].next)
        {
            int v=e[i].v,w=e[i].w;
            if(dis[v][t]>dis[u][t]+w)
            {
                dis[v][t]=dis[u][t]+w;
                if(!vis[v][t])
                {
                    vis[v][t]=1;
                    q.push(node{v,t});
                }
            }
            if(t>0&&dis[v][t-1]>dis[u][t])
            {
                dis[v][t-1]=dis[u][t];
                if(!vis[v][t-1])
                {
                    vis[v][t-1]=1;
                    q.push(node{v,t-1});
                }
            }
        }
    }
    int ans=1e9;
    for(int i=0;i<=k;i++)
    {
        //cout<<dis[i][0]<<" "<<i<<endl;
        ans=min(ans,dis[t][i]);
    }
    printf("%d
",ans);
}
int main()
{
    init();
    scanf("%d%d%d%d%d",&n,&m,&k,&s,&t);
    for(int i=0;i<m;i++)
    {
        int u,v,w;
        scanf("%d%d%d",&u,&v,&w);
        addedge(u,v,w);
        addedge(v,u,w);
    }
    spfa();
    return 0;
}
原文地址:https://www.cnblogs.com/stranger-/p/9615283.html