bzoj2753: [SCOI2012]滑雪与时间胶囊
Posted invoid
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj2753: [SCOI2012]滑雪与时间胶囊相关的知识,希望对你有一定的参考价值。
bfs+最小树形图+kruskal算法。
最小树形图形象地来说就是有向图的最小生成树,这个不能拿kruskal算法或者是prim算法直接求,否则会错。
就是w[u][v]!=w[v][u]的情况。
而这道题用朱刘算法肯定是行不通的。
但是这道题的有向边并不是边的性质,而是点的高度决定的。这样我们就可以分层求最小生成树。
如果加进高度为h的点,只需用kruskal算法选最短的边就可以了,而且不会影响到后面的选择。
于是我们把kruskal算法的排序改成以结尾点高度为第一关键字降序和边长度为第二关键字升序排序。。。(意会,要不看cmp,嗯。)
这样就可以辣。
#include<cstdio> #include<algorithm> #include<cstring> using namespace std; const int maxn = 100000 + 10; const int maxm = 2000000 + 10; int read(){ int x=0,f=1;char ch=getchar(); while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();} while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();} return x*f; } struct Edge { int u,v,d; }e[maxm]; int h[maxn],f[maxn]; int g[maxn],v[maxm],next[maxm],eid; int res1,n,m; long long res2; bool vis[maxn]; int q[maxm],l,r,u; void addedge(int a,int b) { v[eid]=b; next[eid]=g[a]; g[a]=eid++; } bool cmp(Edge a,Edge b) { if(h[a.v]!=h[b.v]) return h[a.v]>h[b.v]; return a.d<b.d; } int find(int x) { return f[x]==x?x:f[x]=find(f[x]); } int main() { memset(g,-1,sizeof(g)); n=read(); m=read(); for(int i=1;i<=n;i++) h[i]=read(); for(int i=1,u,v;i<=m;i++) { u=read(); v=read(); e[i].d=read(); if(h[u]>=h[v]) addedge(u,v); if(h[v]>=h[u]) {addedge(v,u); swap(u,v);} e[i].u=u; e[i].v=v; } sort(e+1,e+m+1,cmp); vis[q[r++]=1]=1,res1=1; while(l<r) { u=q[l++]; for(int i=g[u];~i;i=next[i]) if(!vis[v[i]]) { vis[q[r++]=v[i]]=1; res1++; } } for(int i=1;i<=n;i++) f[i]=i; for(int i=1,ru,rv;i<=m;i++) if(vis[e[i].u]&&vis[e[i].v]) { ru=find(e[i].u); rv=find(e[i].v); if(ru!=rv) { res2+=e[i].d; f[rv]=ru; } } printf("%d %lld\n",res1,res2); return 0; }
以上是关于bzoj2753: [SCOI2012]滑雪与时间胶囊的主要内容,如果未能解决你的问题,请参考以下文章
最小树形图(奇怪的kruskal)SCOI 2012bzoj 2753滑雪与时间胶囊
bzoj 2753: [SCOI2012] 滑雪与时间胶囊 Label:MST