[SCOI2012]滑雪与时间胶囊

来源:互联网 发布:iphone视频制作软件 编辑:程序博客网 时间:2024/04/26 18:55

a180285非常喜欢滑雪。他来到一座雪山,这里分布着M条供滑行的轨道和N个轨道之间的交点(同时也是景点),而且每个景点都有一编号i(1≤i≤N)和一高度Hi。a180285能从景点i滑到景点j当且仅当存在一条i和j之间的边,且i的高度不小于j。与其他滑雪爱好者不同,a180285喜欢用最短的滑行路径去访问尽量多的景点。如果仅仅访问一条路径上的景点,他会觉得数量太少。于是a180285拿出了他随身携带的时间胶囊。这是一种很神奇的药物,吃下之后可以立即回到上个经过的景点(不用移动也不被认为是a180285滑行的距离)。

请注意,这种神奇的药物是可以连续食用的,即能够回到较长时间之前到过的景点(比如上上个经过的景点和上上上个经过的景点)。

现在,a180285站在1号景点望着山下的目标,心潮澎湃。他十分想知道在不考虑时间胶囊消耗的情况下, 以最短滑行距离滑到尽量多的景点的方案(即满足经过景点数最大的前提下使得滑行总距离最小)。

你能帮他求出最短距离和景点数吗?

输入:
输入的第一行是两个整数N,M
接下来1行有N个整数Hi,分别表示每个景点的高度。
接下来M行,表示各个景点之间轨道分布的情况。每行3个整数Ui,Vi,Ki。表示编号为Ui的景点和编号为Vi的景点之间有一条长度为Ki的轨道。

1≤N≤100000

1≤M≤1000000
,1≤Hi≤1000000000,1≤Ki≤1000000000

输出:
输出一行,表示a180285最多能到达多少个景点,以及此时最短的滑行距离总和。

样例输入:

3 33 2 11 2 12 3 11 3 10

样例输出:

3 2

题解:最小生成树,边排序方法需要有改动:终点高度高的边要先做。然后才是按照边权排序。

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<cstdlib>#include<queue>#define LiangJiaJun main#define LL long long#define INF 1999122700using namespace std;struct edge{    int to,next,from;LL w;}e[2400004];int ne,n,m,h[100004],H[100004],cnt=0;LL mcs[100004],ans=0;bool vis[100004];void insert(int u,int v,LL w){     e[++ne].to = v;e[ne].from = u;     e[ne].next = h[u];e[ne].w = w;     h[u] = ne;}int f[100004];int find(int x){return f[x]==x?f[x]:f[x]=find(f[x]);}inline bool dex(edge a, edge b){return H[a.to] == H[b.to]?a.w<b.w:H[a.to]>H[b.to];}queue<int>q;void BFS(){     q.push(1);     while(!q.empty()){        int x=q.front();q.pop();        if(vis[x])continue;        vis[x]=1;        for(int i=h[x];i;i=e[i].next)            if(!vis[e[i].to])q.push(e[i].to);     }     for(int i=1;i<=n;i++) if(vis[i]) ++cnt;}void MST(){     for(int i=1;i<=n;i++) f[i]=i;     sort(e+1,e+ne+1,dex);     for(int i=1;i<=ne;i++){         if(!vis[e[i].from]||!vis[e[i].to]) continue;         int p=find(e[i].from),q=find(e[i].to);         if(p!=q){            f[p]=q;            ans += e[i].w;         }     }}int LiangJiaJun(){    scanf("%d%d",&n,&m);    for(int i=1;i<=n;i++) scanf("%d",&H[i]);    for(int i=1;i<=m;i++){        int u,v;LL w;        scanf("%d%d%lld",&u,&v,&w);        if(H[v] >= H[u]) insert(v,u,w);        if(H[u] >= H[v]) insert(u,v,w);    }    BFS();    MST();    printf("%d %lld\n",cnt,ans);    return 0;}
0 0