a180285 非常喜欢滑雪。他来到一座雪山,这里分布着 mm 条供滑行的轨道和 nn 个轨道之间的交点(同时也是景点),而且每个景点都有一编号(1≤i≤n) 和一高度 hi。
a180285 能从景点 i滑到景点 j当且仅当存在一条 ii 和 jj 之间的边,且 i的高度不小于j。与其他滑雪爱好者不同,a180285 喜欢用最短的滑行路径去访问尽量多的景点。如果仅仅访问一条路径上的景点,他会觉得数量太少。
于是 a18028 5拿出了他随身携带的时间胶囊。这是一种很神奇的药物,吃下之后可以立即回到上个经过的景点(不用移动也不被认为是 a180285 滑行的距离)。
请注意,这种神奇的药物是可以连续食用的,即能够回到较长时间之前到过的景点(比如上上个经过的景点和上上上个经过的景点)。 现在,a180285站在 11 号景点望着山下的目标,心潮澎湃。他十分想知道在不考虑时间胶囊消耗的情况下,以最短滑行距离滑到尽量多的景点的方案(即满足经过景点数最大的前提下使得滑行总距离最小)。你能帮他求出最短距离和景点数吗?
这里不细说思路了,贴一下某位佬的思路分享:
题目大意为:在只能从点权大的点到点权小的点(可以相等)的情况下,从1点出发建立一棵尽可能有更多点的最小生成树
显然我们不能直接求最小生成树,因为有些点应为高度原因无法到达。
对于建立出来的图A,由1点开始宽搜,将扩展到的点和边加入一个新图B,所有扩展到的点便是能到达的最多点。
我们再在这个新图上跑Kruskal求最小生成树,求得最短距离。
对于排序部分,为保证有尽可能多的点在最小生成树里,我们按终点的高度为第一关键字从大到小排序,边长为第二关键字从小到大排序;
这样就能保证拓展的点最多,进而再用最小生成树求最短距离。
既然只能由高点到低点,那么建边就当然是从高点到低点建单向边,这不难理解
建出来的点深搜去找个能到的最远的点,这也不难理解,但是搜索建边呢,可以dfs或者bfs,而且要注意一点是,只要是1点能到的肯定要添加入新图,那么存储原图的方式呢可以有邻接表,或者vector存,然后边权就用map表示,当然邻接表理应是更优的,奈何不会QAQ,所以我选择用平时dfs搜树的存放方式。
还有排序的时候要注意,需要优先按照高度,再按照边长,因为首先确保题意只能由高向低,其次需要保证是最小生成树,所以边权要最低
处理完新图后,可以直接上面跑一遍Kruskal算法,就可以得到最小生成树了~~~
具体详细可以看代码:
#include
#include
using namespace std;
const int maxn=1000000;
#define int long long
int tot,n,m,cnt,sum=1;
int f[maxn],h[maxn];
bool vis[maxn];
vectoredges[maxn];
map,int >value;
bool cmp(edge a,edge b){
return h[a.v]==h[b.v]?a.wh[b.v];
}
void add(int i,int j,int w)
{
e[++tot].w=w;
e[tot].u=i; e[tot].v=j;
}
int findx(int x)
{
if(x==f[x]) return x;
else return f[x]=findx(f[x]);
}
void kruskal()
{
long long res=0,cnt=0;
sort(e+1,e+tot+1,cmp);//排序所有边
for(int i=1;i<=tot;i++)//从小到大枚举所有边
{
int a=e[i].u,b=e[i].v;
long long w=e[i].w;
a=findx(a),b=findx(b);
if(a!=b) //如果a和b不连通,集合里加入这条边
{
res+=w;//最小生成树中所有边的和
f[a]=b;
cnt++;
if(cnt>=sum-1) break;
}
}
cout<>n>>m;
for(i=1;i<=n;i++)
{
cin>>h[i];
f[i]=i;
}
for(i=0;i>u>>v>>k;
if(h[u]>=h[v])
{
edges[u].push_back(v);
if(value[{u,v}]==0) value[{u,v}]=k;
else value[{u,v}]=min(value[{u,v}],k);
}
if(h[u]<=h[v])
{
edges[v].push_back(u);
if(value[{v,u}]==0) value[{v,u}]=k;
else value[{v,u}]=min(value[{v,u}],k);
}
}
vis[1]=1;dfs(1);
// for(i=1;i<=tot;i++)
// {
// cout<