[SCOI2012]滑雪与时间胶囊

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 3
3 2 1
1 2 1
2 3 1
1 3 10

样例输出:

3 2

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

#include
#include
#include
#include
#include
#include
#define LiangJiaJun main
#define LL long long
#define INF 1999122700
using 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.wH[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;
}

你可能感兴趣的:(生成树)