P4822 [BJWC2012]冻结

题目链接

P4822 [BJWC2012]冻结

\(n\) 个点的稠密图。你可以进行 \(k\) 次操作,令某条边权值变成一半,每条边只能变换最多一次。询问从 \(1\)\(n\) 的最短路。
\( n \leq 50, k \leq 50 \text { 。 } \)

解题思路

分层图

考虑将原本的 \(n\) 个点,\(m\) 条边的图复制 \(k+1\) 份,即 \(k+1\) 层,每层之间通过权值减半联系起来,即如果要求减半则往上一层,即如果第 \(i\) 层中存在 \(u,v\) 的边权值为 \(w\)\(i+1\) 中对应 \(u',v'\) 的边,则两层之间通过边 \(u,v'\)\(v,u'\),权值为 \(w/2\) 联系起来,然后用最短路求解即可
时间复杂度:\(O(mklog(nk))\)

代码

// Problem: P4822 [BJWC2012]冻结
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P4822
// Memory Limit: 125 MB
// Time Limit: 3000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

// %%%Skyqwq
#include <bits/stdc++.h>
 
// #define int long long
#define help {cin.tie(NULL); cout.tie(NULL);}
#define pb push_back
#define fi first
#define se second
#define mkp make_pair
using namespace std;
 
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
 
template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; }
template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; }
 
template <typename T> void inline read(T &x) {
    int f = 1; x = 0; char s = getchar();
    while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
    while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
    x *= f;
}

const int N=55;
int n,m,k;
vector<PII> adj[N*N];
int res=0x3f3f3f3f,d[N*N];
bool v[N*N];
void dijkstra()
{
	memset(d,0x3f,sizeof d);
	d[1]=0;
	priority_queue<PII,vector<PII>,greater<PII>> q;
	q.push({0,1});
	while(q.size())
	{
		auto t=q.top();
		q.pop();
		int x=t.se;
		if(v[x])continue;
		v[x]=true;
		for(auto t:adj[x])
		{
			int y=t.fi,w=t.se;
			if(d[y]>d[x]+w)
			{
				d[y]=d[x]+w;
				q.push({d[y],y});
			}
		}
	}
}
int main()
{
    cin>>n>>m>>k;
    for(int i=1;i<=m;i++)
    {
    	int x,y,z;
    	cin>>x>>y>>z;
    	for(int j=0;j<=k;j++)
    	{
    		adj[x+j*n].pb({y+j*n,z}),adj[y+j*n].pb({x+j*n,z});
    		if(j<k)adj[x+j*n].pb({y+(j+1)*n,z>>1}),adj[y+j*n].pb({x+(j+1)*n,z>>1});
    	}
    }
    dijkstra();
    for(int i=0;i<=k;i++)res=min(res,d[n+i*n]);
    cout<<res;
    return 0;
}
posted @ 2022-07-06 11:34  zyy2001  阅读(46)  评论(0编辑  收藏  举报