Loading

[JSOI2010]旅行

链接:https://www.luogu.com.cn/problem/P6029

题目描述:给定一个\(n\)\(m\)条边的无向图,可以交换\(k\)组边,求\(1\)\(n\)的最短路。

题解:发现值域都比较小,考虑\(dp\)

我们可以发现,存在一个段点\(L\),使得前\(L\)条边只换不走,后面的\(m-L\)条边换为前\(L\)条边,这样走一定不会使答案更差。

\(dp_{i,j,k}\)表示到节点\(i\),在前\(L\)条边中选了\(j\)条边,轮换了\(k\)次的最短路。
则有:

当前边在前\(L\)条边时:

\(dp_{i,j,k}+edge_{j+1}->dp_{v,j+1,k}\)

当前边不在前\(L\)条边时:

\(dp_{i,j,k}+edge_{now}->dp_{v,j,k}\)

\(dp_{i,j,k}+edge_{j+1}->dp_{v,j,k+1}\)

转移可以建分层图跑最短路。

#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;
} 
posted @ 2022-12-14 21:28  zhouhuanyi  阅读(42)  评论(0)    收藏  举报