【BZOJ 2753】 2753: [SCOI2012]滑雪与时间胶囊 (分层最小树形图,MST)
2753: [SCOI2012]滑雪与时间胶囊
Time Limit: 50 Sec Memory Limit: 128 MB
Submit: 2457 Solved: 859Description
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。Source
【分析】
说实话我看的时候也觉得是最小树形图。【然后表示朱刘算法忘得差不多了。。
但其实这个MST可以搞定ORZ。。
首先BFS,把能到的点标记一下,顺便求第一问。
你可以看成同一高度的SCC缩点(里面当然直接MST就好的了),那就是个分层图,按高度大小分的话呢,是一个DAG。
DAG的话、跑朱刘是不会找到环的,于是你第一步就搞定了。【应该是这样的意思吧,网上的人不知道干嘛。。
然后其实可以把上面整个过程合成一个,就是按照 第一键值为终点的高度,第二键值为边的权值,跑MST 就行了。
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<iostream> 5 #include<algorithm> 6 #include<queue> 7 using namespace std; 8 #define Maxn 1000010 9 #define Maxm 1000010 10 #define LL long long 11 12 int h[Maxn],fa[Maxn]; 13 struct node 14 { 15 int x,y,c,next; 16 }t[Maxm*2]; 17 int first[Maxn],len; 18 19 void ins(int x,int y,int c) 20 { 21 if(h[x]>h[1]) return; 22 t[++len].x=x;t[len].y=y;t[len].c=c; 23 t[len].next=first[x];first[x]=len; 24 } 25 26 bool cmp(node x,node y) {return (h[x.y]==h[y.y])?(x.c<y.c):(h[x.y]>h[y.y]);} 27 28 int a1=1,st; 29 LL a2=0; 30 bool vis[Maxn]; 31 queue<int > q; 32 void bfs() 33 { 34 memset(vis,0,sizeof(vis)); 35 vis[st]=1;q.push(st); 36 while(!q.empty()) 37 { 38 int x=q.front(); 39 for(int i=first[x];i;i=t[i].next) 40 { 41 int y=t[i].y; 42 if(!vis[y]) 43 { 44 a1++; 45 q.push(y); 46 vis[y]=1; 47 } 48 } 49 q.pop(); 50 } 51 } 52 53 int ffa(int x) 54 { 55 if(fa[x]!=x) fa[x]=ffa(fa[x]); 56 return fa[x]; 57 } 58 59 int main() 60 { 61 int n,m; 62 scanf("%d%d",&n,&m); 63 for(int i=1;i<=n;i++) scanf("%d",&h[i]); 64 len=0; 65 memset(first,0,sizeof(first)); 66 for(int i=1;i<=m;i++) 67 { 68 int x,y,c; 69 scanf("%d%d%d",&x,&y,&c); 70 if(h[x]<h[y]) swap(x,y); 71 if(h[x]==h[y]) {ins(x,y,c);ins(y,x,c);} 72 else ins(x,y,c); 73 } 74 st=1;bfs(); 75 sort(t+1,t+1+len,cmp); 76 for(int i=1;i<=n;i++) fa[i]=i; 77 for(int i=1;i<=len;i++) 78 { 79 if(!vis[t[i].x]||!vis[t[i].y]) continue; 80 if(ffa(t[i].x)!=ffa(t[i].y)) 81 { 82 a2+=t[i].c; 83 fa[ffa(t[i].x)]=ffa(t[i].y); 84 } 85 } 86 printf("%d %lld\n",a1,a2); 87 return 0; 88 }
要开long long
2017-03-29 10:05:58