1. 程式人生 > >bzoj2753[SCOI2012]滑雪與時間膠囊 最小生成樹

bzoj2753[SCOI2012]滑雪與時間膠囊 最小生成樹

.com define out sco bit fin discus def fine

Time Limit: 50 Sec Memory Limit: 128 MB
Submit: 2843 Solved: 993
[Submit][Status][Discuss]

Description

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

Input

輸入的第一行是兩個整數N,M。 接下來1行有N個整數Hi,分別表示每個景點的高度。 接下來M行,表示各個景點之間軌道分布的情況。每行3個整數,Ui,Vi,Ki。表示 編號為Ui的景點和編號為Vi的景點之間有一條長度為Ki的軌道。

Output

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

Sample Input


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

Sample Output

3 2

HINT

【數據範圍】

對於30%的數據,保證 1<=N<=2000


對於100%的數據,保證 1<=N<=100000

對於所有的數據,保證 1<=M<=1000000,1<=Hi<=1000000000,1<=Ki<=1000000000。

很詭異的正解,並不是很懂
首先一個搜索把1號點可以到的所有點打上標記,需要聯通的點就只有被標記的點,沒被標記的點可以直接不管
然後計算最小的代價使得1號點可以到達所有的點。如果是無向圖的話,豈不是一棵最小生成樹?
繼續想,可以發現1號點必然不矮於其它點,要讓點聯通,先從1號點走到較高的點,再從較高的點走向下一個較高的點...
因此把它看成是一個無向圖,做最小生成樹 排序第一關鍵字為目標點高度,第二關鍵字位邊權

 1 #include<bits/stdc++.h>
 2
#define N 100050 3 #define ll long long 4 using namespace std; 5 int n,m,tot,cnt,hd[N],h[N],q[N],vis[N],fa[N]; 6 struct edge{int u,v,w,next;}e[N*20];ll sum; 7 char gc(){ 8 static char s[1000000],*p1,*p2; 9 if(p1==p2)p2=(p1=s)+fread(s,1,1000000,stdin); 10 if(p1==p2)return EOF;return *p1++; 11 } 12 int read(){ 13 int x=0;char ch=gc(); 14 while(ch<0||ch>9)ch=gc(); 15 while(ch>=0&&ch<=9)x=(x<<3)+(x<<1)+ch-0,ch=gc(); 16 return x; 17 } 18 void adde(int u,int v,int w){ 19 e[++tot].v=v; 20 e[tot].u=u; 21 e[tot].w=w; 22 e[tot].next=hd[u]; 23 hd[u]=tot; 24 } 25 void bfs(){ 26 int h=1,t=0;q[++t]=1;vis[1]=1;cnt=1; 27 while(h<=t){ 28 int u=q[h++]; 29 for(int i=hd[u];i;i=e[i].next){ 30 int v=e[i].v; 31 if(vis[v])continue; 32 vis[v]=1;cnt++;q[++t]=v; 33 } 34 } 35 } 36 int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);} 37 bool cmp(edge a,edge b){return h[a.v]==h[b.v]?a.w<b.w:h[a.v]>h[b.v];} 38 int main(){ 39 n=read();m=read(); 40 for(int i=1;i<=n;i++)h[i]=read(); 41 for(int i=1;i<=m;i++){ 42 static int u,v,w; 43 u=read();v=read();w=read(); 44 if(h[u]>=h[v])adde(u,v,w); 45 if(h[v]>=h[u])adde(v,u,w); 46 } 47 bfs();int num=1; 48 for(int i=1;i<=n;i++)fa[i]=i; 49 sort(e+1,e+1+tot,cmp); 50 for(int i=1;i<=tot;i++){ 51 if(!vis[e[i].u]||!vis[e[i].v])continue; 52 int fu=find(e[i].u),fv=find(e[i].v); 53 if(fu==fv)continue; 54 num++;sum+=e[i].w; 55 fa[fu]=fv; 56 if(num==cnt)break; 57 } 58 printf("%d %lld\n",cnt,sum); 59 return 0; 60 }

bzoj2753[SCOI2012]滑雪與時間膠囊 最小生成樹