Live2D

【SCOI2012】滑雪

题目太长不想放
从1号点开始,只能向高度更低或者相同的点走
可以返回之前走过的点
在经过的点最多的前提下,走过的路径最短为多少

这道sb题居然改了一个多小时
是真的离退役不远了吧

思路很简单,向每个高点向低点连边
广搜一遍,看有哪些点是可以达到的

然后在新图上面跑最小生成树即可

改了那么久,最重要的是看到bfs就无脑写SPFA版bfs
结果遇到同高度的环死都出不去

自裁吧

#include<bits/stdc++.h>
#define ll long long
#define N 100005
#define M 1000005
using namespace std;

int n,m,u,v,w;
int h[N];
ll canget=0,mindis=0;

struct Edge
{
	int next,to,dis;
}edge[M<<1];
int cnt=0,head[M];

inline void add_edge(int from,int to,int dis)
{
	edge[++cnt].next=head[from];
	edge[cnt].to=to;
	edge[cnt].dis=dis;
	head[from]=cnt;
}

template<class T>inline void read(T &res)
{
	char c;T flag=1;
	while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;res=c-'0';
	while((c=getchar())>='0'&&c<='9')res=res*10+c-'0';res*=flag;
}

struct NewEdge
{
	int u,v,w;
}nedge[M<<1];
int ncnt=0;

//bool vis[N];
//queue<int> q;
//void bfs()
//{
//	vis[1]=1;
//	q.push(1);
//	while(!q.empty())
//	{
//		int u=q.front();q.pop();vis[u]=0;
//		for(register int i=head[u];i;i=edge[i].next)
//		{
//			int v=edge[i].to;
//			nedge[++ncnt].u=u;
//			nedge[ncnt].v=v;
//			nedge[ncnt].w=edge[i].dis;
//			if(!vis[v])
//			{
//				canget++;
//				q.push(v);
//				vis[v]=1;
//			}
//		}
//	}
//}


bool vis[N];
int q[N],qr,ql;
void bfs()
{
    q[++qr]=1;
	vis[1]=1;
    while(ql<qr)
	{
		int u=q[++ql];
        for(register int i=head[u];i;i=edge[i].next)
		{
			int v=edge[i].to;
            nedge[++ncnt].u=u;
			nedge[ncnt].v=v;
			nedge[ncnt].w=edge[i].dis;
            if(!vis[v])
			{
				canget++;
                vis[v]=1;
                q[++qr]=(v);
            }
        }
    }
}

bool cmp(NewEdge a,NewEdge b)
{
	return h[a.v]==h[b.v]?a.w<b.w:h[a.v]>h[b.v];
}

int fa[N];
int find(int x) {return x==fa[x]?x:fa[x]=find(fa[x]);}
void kruskal()
{
	sort(nedge+1,nedge+ncnt+1,cmp);
	for(register int i=1;i<=ncnt;++i)
	{
		int fx=find(nedge[i].u);
		int fy=find(nedge[i].v);
		if(fx!=fy)
		{
			fa[fx]=fy;
			mindis+=nedge[i].w;
		}
	}
}

int main()
{
	read(n);read(m);
	for(register int i=1;i<=n;++i) read(h[i]),fa[i]=i;
	for(register int i=1;i<=m;++i)
	{
		read(u);read(v);read(w);
		if(h[u]>=h[v]) add_edge(u,v,w);
		if(h[u]<=h[v]) add_edge(v,u,w);
	}
	bfs();
	kruskal();
	printf("%lld %lld\n",canget+1,mindis);
	return 0;
}
/*
5 5
8 10 5 4 3
1 2 20
1 3 10
2 4 30
3 4 7
3 5 8
*/
posted @ 2019-10-21 21:02  tqr06  阅读(101)  评论(0编辑  收藏  举报