链接
背景
(CCF) (NOI) (2011) 吉林省代表队选拔, (Luogu) (P4568/BZOJ2763)
题意
给定 (n) 个点, (m) 条边的两个端点 (x,y) ,规定一条路径上最多可以使得 (k) 条边变成 (0) 。求 (s) 到 (t) 的最短路径长度。
解法
分层图最短路模板。
由于可以免费 (k) 次,建 (k) 层图(假定变成 (0) 的边数越多图越高)即可。
注意每条边在每一层上连一遍,然后 (x) 向高一层的 (y) 连 (0) 边, (y) 向高一层的 (x) 连 (0) 边。
从 (s) 点开始 (dijkstra) ,答案是所有层上第 (t) 个点的最短路的最小值。
代码
$View$ $Code$
```cpp
#include
using namespace std;
inline int read()
{
int ret=0,f=1;
char ch=getchar();
while(ch>'9'||ch<'0')
{
if(ch=='-')
f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9')
{
ret=(ret<<1)+(ret<<3)+ch-'0';
ch=getchar();
}
return ret*f;
}
int n,m,k,s,t,u,v,w;
int dis[200005],ans=2e9;
int num,head[200005];
bool vis[200005];
struct edge
{
int ver,nxt,w;
}e[3000005];
inline void adde(int u,int v,int w)
{
e[++num].ver=v;
e[num].w=w;
e[num].nxt=head[u];
head[u]=num;
}
void dijkstra(int s)
{
memset(dis,0x3f,sizeof(dis));
memset(vis,0,sizeof(vis));
priority_queue > q;
dis[s]=0;
q.push(make_pair(0,s));
while(!q.empty())
{
int x=q.top().second;
q.pop();
if(vis[x])
continue;
vis[x]=1;
for(register int i=head[x];i;i=e[i].nxt)
{
int y=e[i].ver,w=e[i].w;
if(dis[x]+w