1. 程式人生 > >[SCOI2012]滑雪 洛谷p2573

[SCOI2012]滑雪 洛谷p2573

題目描述

a180285非常喜歡滑雪。他來到一座雪山,這裡分佈著MM條供滑行的軌道和NN個軌道之間的交點(同時也是景點),而且每個景點都有一編號ii(1 \le i \le N1≤i≤N)和一高度H_iHi​。a180285能從景點ii滑到景點jj當且僅當存在一條ii和jj之間的邊,且ii的高度不小於jj。 與其他滑雪愛好者不同,a180285喜歡用最短的滑行路徑去訪問儘量多的景點。如果僅僅訪問一條路徑上的景點,他會覺得數量太少。於是a180285拿出了他隨身攜帶的時間膠囊。這是一種很神奇的藥物,吃下之後可以立即回到上個經過的景點(不用移動也不被認為是a180285 滑行的距離)。請注意,這種神奇的藥物是可以連續食用的,即能夠回到較長時間之前到過的景點(比如上上個經過的景點和上上上個經過的景點)。 現在,a180285站在11號景點望著山下的目標,心潮澎湃。他十分想知道在不考慮時間膠囊消耗的情況下,以最短滑行距離滑到儘量多的景點的方案(即滿足經過景點數最大的前提下使得滑行總距離最小)。你能幫他求出最短距離和景點數嗎?

輸入輸出格式

輸入格式:

 

輸入的第一行是兩個整數N,MN,M。

接下來11行有NN個整數H_iHi​,分別表示每個景點的高度。

接下來MM行,表示各個景點之間軌道分佈的情況。每行33個整數,U_i,V_i,K_iUi​,Vi​,Ki​。表示編號為U_iUi​的景點和編號為V_iVi​的景點之間有一條長度為K_iKi​的軌道。

 

輸出格式:

 

輸出一行,表示a180285最多能到達多少個景點,以及此時最短的滑行距離總和。

 

輸入輸出樣例

輸入樣例#1: 複製

3 3 
3 2 1 
1 2 1 
2 3 1 
1 3 10 

輸出樣例#1: 複製

3 2

說明

【資料範圍】

對於30\%30%的資料,保證 1 \le N \le 20001≤N≤2000

對於100\%100%的資料,保證 1 \le N \le 10^51≤N≤105

對於所有的資料,保證 1 \le M \le 10^61≤M≤106 , 1 \le H_i \le 10^91≤Hi​≤109 ,1 \le K_i \le 10^91≤Ki​≤109。

 

dfs記錄所能能到達的點和邊,然後把邊以到達的點得高度為第一關鍵字,邊長為第二關鍵字跑克魯斯卡爾。

#include<bits/stdc++.h>
#define f(i,l,r) for(i=(l);i<=(r);i++)
using namespace std;
const int MAXN=100005,MAXM=1000005;
struct Edge{
	int v,w,nxt;
}e[MAXM<<1];
int H[MAXN],h[MAXN],vis[MAXN];
struct Node{
	int u,v,w;
	bool operator < (const Node& tmp)const{
		if(H[v]==H[tmp.v]) return w<tmp.w;
		return H[v]>H[tmp.v];
	}
}a[MAXM<<1];

int fa[MAXN];
int n,m;
int num,cnt,tot;
inline void add(int u,int v,int w)
{
	e[tot].v=v;
	e[tot].w=w;
	e[tot].nxt=h[u];
	h[u]=tot++;
}
void dfs(int u,int fa)
{
	int i;
	if(!vis[u]) num++;
	vis[u]=1;
	for(i=h[u];~i;i=e[i].nxt){
		int v=e[i].v,w=e[i].w;
		if(v==fa) continue;
		a[++cnt].u=u;
		a[cnt].v=v;
		a[cnt].w=w;
		if(vis[v]) continue;
		dfs(v,u);
	}
}
inline void Makeset()
{
	int i;
	f(i,1,n) fa[i]=i;
}
inline int Find(int x)
{
	return fa[x]==x?x:fa[x]=Find(fa[x]);
}
inline bool Union(int x,int y)
{
	x=Find(x);y=Find(y);
	if(x==y) return false;
	fa[x]=y;
	return true;
}
int main()
{
	ios::sync_with_stdio(false);
	int i,j,u,v,w;
	long long ans=0;
	int res=0;
	memset(h,-1,sizeof(h));
	cin>>n>>m;
	f(i,1,n){
		cin>>H[i];
	}
	f(i,1,m){
		cin>>u>>v>>w;
		if(H[u]>=H[v]) add(u,v,w);
		if(H[v]>=H[u]) add(v,u,w);
	}
	dfs(1,-1);
//	cout<<num<<"GGGGG"<<endl;
//	f(i,1,cnt){
//		cout<<a[i].u<<" "<<a[i].v<<" "<<a[i].w<<endl;
//	}
	sort(a+1,a+1+cnt);
	Makeset();
	f(i,1,cnt){
		u=a[i].u;v=a[i].v;w=a[i].w;
		if(Union(u,v)){
			ans+=w;
			res++;
			if(res==num-1) break;
		}
	}
	cout<<num<<" "<<ans<<endl;
	return 0;
}