bzoj2753滑雪与时间胶囊

来源:互联网 发布:川航张芸芸事件知乎 编辑:程序博客网 时间:2024/04/24 17:22

http://www.lydsy.com/JudgeOnline/problem.php?id=2753


因为景点数要尽可能多,所以一定要在景点数最大的情况下代价最小。


景点数要尽可能大,就是从1能到的所有点都要被遍历。


所以利用了一个dfs+vis数组。  遍历复杂度是O(n)的。


然后代价尽可能小。


考虑一些生成树的边,如果两条边的出边的点一样高,代价越小越优; 否则,出边的点要尽可能高。

因为我们要尽可能先走高的点,才能保证访问的点的个数越多,其次才是权值最小。


#include<cstdio>#include<cstring>#include<cstdlib>#include<algorithm>#include<queue>#include<cmath>#include<iostream>#define ll long longusing namespace std;const int maxn=100000+20;struct node{int u,v,next;ll w;}e[maxn*20];int head[maxn];int fa[maxn];int find(int x){if(fa[x]==x)return x;return fa[x]=find(fa[x]);}int k;void add(int u,int v,ll w){e[k].u=u;e[k].v=v;e[k].w=w;e[k].next=head[u];head[u]=k++;}int n,m;int h[maxn];int vis[maxn];int tot;void dfs(int u,int f){vis[u]=1;tot++;for(int i=head[u];~i;i=e[i].next){int v=e[i].v;if(v==f)continue;if(!vis[v])dfs(v,u);}}bool cmp(node x,node y){if(h[x.v]==h[y.v])return x.w<y.w;return h[x.v]>h[y.v];}void work(){printf("%d ",tot);ll ans=0;sort(e+1,e+k+1,cmp);int pp=0;for(int i=1;i<=k;i++){int u=e[i].u;int v=e[i].v;int f1=find(u),f2=find(v);if(!vis[u]||!vis[v])continue;if(f1==f2)continue;fa[f1]=f2;pp++;ans+=e[i].w;if(pp==tot-1)break;}printf("%lld\n",ans);}int main(){memset(vis,0,sizeof(vis));memset(head,-1,sizeof(head));k=1;scanf("%d%d",&n,&m);for(int i=1;i<=n;i++)scanf("%d",&h[i]);for(int i=1;i<=n;i++)fa[i]=i;tot=0;for(int i=1;i<=m;i++){int u,v;ll w;scanf("%d%d%lld",&u,&v,&w);if(h[u]>=h[v])add(u,v,w);if(h[v]>=h[u])add(v,u,w);}dfs(1,-1);work();return 0;}


0 0
原创粉丝点击