标签:win print 电话线 main inf activity 作者 使用 ref
https://www.luogu.org/problem/P1948
K次免费机会-->每个点(i)拆成(i,k),表示使用了k次免费机会后的i;
于是就将平常的一张图(二维)转换为立体图(三维),但实现上还是二维的
每层跟平常一样建边,然后再在两层之间建图作为联系,即免费边。
最后看每层的(n,k)点的dis(使用了k次机会后到n的花费);
dis[v]>dis[u]+val[i]根据题改为dis[v]>max(dis[u],val[i]);
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10,M=1e7+10,INF=1e9;
int n,p,k;
int head[N],nex[M*2],to[M*2],val[M*2],tot;
void build(int u,int v,int w){tot++;nex[tot]=head[u];to[tot]=v;val[tot]=w;head[u]=tot;}
bool vis[N];
int dis[N];
priority_queue<pair<int,int> >q;
void spfa()
{
for(int i=1;i<=n*(k+1);i++)dis[i]=INF;
q.push(make_pair(-0,1));
dis[1]=0;
while(!q.empty())
{
int u=q.top().second;q.pop();
if(vis[u])continue;vis[u]=1;
for(int i=head[u];i;i=nex[i])
{
int v=to[i],w=max(dis[u],val[i]);
if(dis[v]>w)
{
dis[v]=w;
q.push(make_pair(-w,v));
}
}
}
}
int main()
{
scanf("%d%d%d",&n,&p,&k);
for(int u,v,w,i=1;i<=p;i++)
{
scanf("%d%d%d",&u,&v,&w);
for(int j=0;j<=k;j++)
{
build(u+j*n,v+j*n,w);
build(v+j*n,u+j*n,w);
}
for(int j=0;j<k;j++)
{
build(u+j*n,v+(j+1)*n,0);
build(v+j*n,u+(j+1)*n,0);
}
}
spfa();
int ans=INF;
for(int i=0;i<=k;i++)
{
ans=min(ans,dis[n+i*n]);
}
if(ans!=INF)printf("%d",ans);
else printf("-1");
}
作者:yfxJ518
链接:https://www.acwing.com/activity/content/code/content/124992/
来源:AcWing
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
标签:win print 电话线 main inf activity 作者 使用 ref
原文地址:https://www.cnblogs.com/fengJ518/p/11628114.html