通信线路
大意
n个点,m条双向边,求从1~n的最小费用,你可以其中免费k条线路。
思路
将dis数组改为二位,用多出来的一维表示当前的线路免费了多少次,在正常跑完spfa 后判断每条边免费或不免费的费用,最后费用 a n s = min 0 ≤ i < k d p [ n ] [ i ] ans=\min _{0\leq i< k}\ {dp[n][i]} ans=min0≤i<k dp[n][i]
code
#include<bits/stdc++.h>
using namespace std;
const int N=1000086;
int n,m,p[N],cnt=0,k;
struct node
{
int next,to;
}edge[500086];
int head[N];
bool vis[N];
void add(int x,int y,int z)
{
edge[++cnt].to=y;
edge[cnt].next=head[x];
p[cnt]=z;
head[x]=cnt;
}
int dis[1100][1100];
void spfa(int s)
{
memset(dis,0x3f,sizeof(dis));
memset(vis,0,sizeof(vis));
queue<int> q;
q.push(s);
dis[s][0]=0;
vis[s]=1;
while(!q.empty())
{
int x=q.front();
q.pop();
vis[x]=0;
for(int i=head[x];i;i=edge[i].next)
{
int j=edge[i].to;
int w=max(dis[x][0],p[i]);
if(dis[j][0]>w)
{
dis[j][0]=w;
if(vis[j]==0)
{
vis[j]=1;
q.push(j);
}
}
for(int l=1;l<=k;l++)
{
int w=min(dis[x][l-1],max(dis[x][l],p[i]));
if(dis[j][l]>w)
{
dis[j][l]=w;
if(vis[j]==0)
{
vis[j]=1;
q.push(j);
}
}
}
}
}
}
int main()
{
freopen("test.in","r",stdin);
freopen("test.out","w",stdout);
scanf("%d%d%d",&n,&m,&k);
for(int i=1;i<=m;i++)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
add(x,y,z);
add(y,x,z);
}
spfa(1);
int ans=0x3f3f3f;
for(int i=0;i<=k;i++)
{
ans=min(ans,dis[n][i]);
}
if(ans==0x3f3f3f) printf("-1\n");
else printf("%d\n",ans);
return 0;
}