[JSOI2010]旅行
链接:https://www.luogu.com.cn/problem/P6029
题目描述:给定一个个条边的无向图,可以交换组边,求到的最短路。
题解:发现值域都比较小,考虑。
我们可以发现,存在一个段点,使得前条边只换不走,后面的条边换为前条边,这样走一定不会使答案更差。
令表示到节点,在前条边中选了条边,轮换了次的最短路。
则有:
当前边在前条边时:
当前边不在前条边时:
转移可以建分层图跑最短路。
#include<iostream>
#include<queue>
#include<algorithm>
using namespace std;
struct node
{
int v,nxt,data;
};
struct edg
{
int u,v,data;
bool operator < (const edg &a)const
{
return data<a.data;
}
};
struct reads
{
int num,data;
bool operator < (const reads &a)const
{
return data>a.data;
}
};
node edge[2000001];
edg edges[1000001];
int n,m,k,head[1000001],dis[1000001],len;
bool used[1000001];
void add(int x,int y,int z)
{
edge[++len].v=y;
edge[len].data=z;
edge[len].nxt=head[x];
head[x]=len;
return;
}
int d(int x,int y,int z)
{
return (x-1)*(k+1)*(m+1)+y*(m+1)+z+1;
}
reads tmp;
reads make_reads(int x,int y)
{
tmp.num=x;
tmp.data=y;
return tmp;
}
priority_queue<reads>q;
void dijkstra()
{
int top;
for (int i=1;i<=d(n,k,m);++i)
{
dis[i]=1e9;
used[i]=0;
}
q.push(make_reads(1,0));
dis[1]=0;
while (!q.empty())
{
top=q.top().num;
q.pop();
if (used[top])
continue;
used[top]=1;
for (int i=head[top];i>0;i=edge[i].nxt)
if (dis[edge[i].v]>dis[top]+edge[i].data)
{
dis[edge[i].v]=dis[top]+edge[i].data;
q.push(make_reads(edge[i].v,dis[edge[i].v]));
}
}
return;
}
int main()
{
int x,y,ans=1e9;
cin>>n>>m>>k;
for (int i=1;i<=m;++i)
cin>>edges[i].u>>edges[i].v>>edges[i].data;
sort(edges+1,edges+m+1);
for (int L=0;L<=m;++L)
{
len=0;
for (int i=1;i<=d(n,k,m);++i)
head[i]=0;
for (int i=1;i<=m;++i)
{
for (int j=0;j<=k;++j)
for (int t=0;t<=L;++t)
{
if (i<=L&&t+1<=L)
{
add(d(edges[i].u,j,t),d(edges[i].v,j,t+1),edges[t+1].data);
add(d(edges[i].v,j,t),d(edges[i].u,j,t+1),edges[t+1].data);
}
else if (i>L)
{
add(d(edges[i].u,j,t),d(edges[i].v,j,t),edges[i].data);
add(d(edges[i].v,j,t),d(edges[i].u,j,t),edges[i].data);
}
}
for (int j=0;j<=k-1;++j)
for (int t=0;t<=L-1;++t)
if (i>L)
{
add(d(edges[i].u,j,t),d(edges[i].v,j+1,t+1),edges[t+1].data);
add(d(edges[i].v,j,t),d(edges[i].u,j+1,t+1),edges[t+1].data);
}
}
dijkstra();
for (int i=0;i<=k;++i)
ans=min(ans,dis[d(n,i,L)]);
}
cout<<ans<<endl;
return 0;
}
作者:zhouhuanyi
出处:https://www.cnblogs.com/zhouhuanyi/p/16983634.html
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)