bzoj2753: [SCOI2012]滑雪与时间胶囊
生活随笔
收集整理的這篇文章主要介紹了
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; }轉載于:https://www.cnblogs.com/invoid/p/5635995.html
總結
以上是生活随笔為你收集整理的bzoj2753: [SCOI2012]滑雪与时间胶囊的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 欢迎大家多来关注下!
- 下一篇: C#语言基础——结构体和枚举类型