[USACO09FEB]改造路题解

题目链接

今天机房模拟赛的题目,先用爆搜做的,后面去写了dijkstra(没想到过掉了

本菜鸡之前并没有学过分层图,所以我感觉用的是dijkstra加动态规划的思想

我们用\(dis[i][j]\)来表示到从1号牧场到第\(i\)号牧场升级\(j\)条路所花的最短时间,设第\(x\)号牧场与第\(i\)号牧场相连通,\(road(i,x)\)表示\(i\)\(x\)的路径长度,从\(i\)\(x\),要么升级路径,要么就不升级,那么不难发现

\(dis[x][j]=min(dis[i][j]+road(i,x),dis[x][j])\)

\(dis[x][j+1]=min(dis[i][j],dis[x][j+1])\)

接下来讲讲我的dijkstra,用\(k\)个堆来存最小的\(dis[i]\),从不升级路径枚举到升级k条路径,下面是这一部分的代码

	for(int j=0; j<=k; j++)  //枚举升级路径的条数
	{
		memset(vis,0,sizeof(vis));
		while(!q[j].empty())
		{
			p=q[j].top();
			q[j].pop();
			if(vis[p.a]==0) //未访问过
			{
				vis[p.a]=1;
				for(int i=0; i<l[p.a].size(); i++)
					if(vis[l[p.a][i]]==0)
					{
						son=l[p.a][i]; //与i相连的节点
						if(p.sum+l1[p.a][i]<dis[son][j]) //不升级路径
						{
							dis[son][j]=p.sum+l1[p.a][i];
							node txt;
							txt.a=l[p.a][i],txt.sum=dis[son][j];
							q[j].push(txt);
						}
						if(j!=k&&p.sum<dis[son][j+1]) //升级路径
						{
							dis[son][j+1]=p.sum;
							node txt;
							txt.a=l[p.a][i],txt.sum=dis[son][j+1];
							q[j+1].push(txt);
						}
					}
			}
		}
	}

也没什么其他要讲的啦,接下来是全部代码

#include<bits/stdc++.h>
using namespace std;
#define int long long //注意要long long!!! 
struct node
{
	int a,sum;
	bool operator<(const node&aaa)const
	{
		return aaa.sum<sum;
	}
} p;
int n,m,k,dis[10003][23],x,y,w,ans=1e9,vis[10003],son;
vector<int>l[10003],l1[10003]; //vector存图
priority_queue<node>q[23]; //用堆优化dijkstra 
signed main()
{
	scanf("%d%d%d",&n,&m,&k);
	for(int i=1; i<=m; i++)
	{
		scanf("%d%d%d",&x,&y,&w);
		l[x].push_back(y),l[y].push_back(x),l1[x].push_back(w),l1[y].push_back(w); //存图
	}
	for(int i=1; i<=n; i++)
		for(int j=0; j<=k; j++)
			dis[i][j]=1e9; //记得赋初值
	dis[1][0]=0,p.a=1,p.sum=0;
	q[0].push(p);
	for(int j=0; j<=k; j++)  //枚举升级路径的条数
	{
		memset(vis,0,sizeof(vis));
		while(!q[j].empty())
		{
			p=q[j].top();
			q[j].pop();
			if(vis[p.a]==0) //未访问过
			{
				vis[p.a]=1;
				for(int i=0; i<l[p.a].size(); i++)
					if(vis[l[p.a][i]]==0)
					{
						son=l[p.a][i]; //与i相连的节点
						if(p.sum+l1[p.a][i]<dis[son][j]) //不升级路径
						{
							dis[son][j]=p.sum+l1[p.a][i];
							node txt;
							txt.a=l[p.a][i],txt.sum=dis[son][j];
							q[j].push(txt);
						}
						if(j!=k&&p.sum<dis[son][j+1]) //升级路径
						{
							dis[son][j+1]=p.sum;
							node txt;
							txt.a=l[p.a][i],txt.sum=dis[son][j+1];
							q[j+1].push(txt);
						}
					}
			}
		}
	}
	cout<<dis[n][min(m,k)];
	return 0;
}
posted @ 2019-11-24 08:29  dz_ice  阅读(156)  评论(0编辑  收藏  举报