• 【刷题】BZOJ 2753 [SCOI2012]滑雪与时间胶囊


    Description

    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。

    Solution

    另类kruskal
    第一问直接bfs
    第二问如果直接跑最小生成树,可能会弄出不连通的图,因为kruskal是对于无向图的。那么这题的有向图,我们可以让它变得有序,从而使kruskal变得正确,连出的图联通。第一关键字按照终点的高度从大到小,第二关键字按照边的长度,将边排序。
    首先,高度一样时,各个景点可以互相到达,那么就是个无向图了,边越短越先选;如果高度不一样,那么只有先连高度更高的,才能到达高度更低的,保证所有点与 (1) 号点联通。

    #include<bits/stdc++.h>
    #define ui unsigned int
    #define ll long long
    #define db double
    #define ld long double
    #define ull unsigned long long
    const int MAXN=100000+10,MAXM=1000000+10;
    int n,m,h[MAXN],fa[MAXN],p[MAXN],use[MAXN],e,to[MAXM<<1],nex[MAXM<<1],beg[MAXN],snt;
    ll ans1,ans2;
    std::queue<int> q;
    struct node{
    	int u,v,k;
    	inline bool operator < (const node &A) const {
    		return h[v]>h[A.v]||(h[v]==h[A.v]&&k<A.k);
    	};
    };
    node side[MAXM<<1];
    template<typename T> inline void read(T &x)
    {
    	T data=0,w=1;
    	char ch=0;
    	while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
    	if(ch=='-')w=-1,ch=getchar();
    	while(ch>='0'&&ch<='9')data=((T)data<<3)+((T)data<<1)+(ch^'0'),ch=getchar();
    	x=data*w;
    }
    template<typename T> inline void write(T x,char ch='')
    {
    	if(x<0)putchar('-'),x=-x;
    	if(x>9)write(x/10);
    	putchar(x%10+'0');
    	if(ch!='')putchar(ch);
    }
    template<typename T> inline void chkmin(T &x,T y){x=(y<x?y:x);}
    template<typename T> inline void chkmax(T &x,T y){x=(y>x?y:x);}
    template<typename T> inline T min(T x,T y){return x<y?x:y;}
    template<typename T> inline T max(T x,T y){return x>y?x:y;}
    inline void insert(int x,int y)
    {
    	to[++e]=y;
    	nex[e]=beg[x];
    	beg[x]=e;
    }
    inline void bfs()
    {
    	p[1]=1;
    	q.push(1);
    	while(!q.empty())
    	{
    		int x=q.front();
    		q.pop();
    		p[x]=0;use[x]=1;
    		for(register int i=beg[x];i;i=nex[i])
    			if(!p[to[i]]&&!use[to[i]])p[to[i]]=1,q.push(to[i]);
    	}
    	for(register int i=1;i<=n;++i)
    		if(use[i])ans1++;
    }
    inline int found(int x)
    {
    	if(fa[x]!=x)fa[x]=found(fa[x]);
    	return fa[x];
    }
    int main()
    {
    	read(n);read(m);
    	for(register int i=1;i<=n;++i)read(h[i]);
    	for(register int i=1;i<=m;++i)
    	{
    		int u,v,k;read(u);read(v);read(k);
    		if(h[u]>=h[v])side[++snt]=(node){u,v,k},insert(u,v);
    		if(h[v]>=h[u])side[++snt]=(node){v,u,k},insert(v,u);
    	}
    	bfs();
    	std::sort(side+1,side+snt+1);
    	for(register int i=1;i<=n;++i)fa[i]=i;
    	for(register int i=1;i<=snt;++i)
    	{
    		if(!use[side[i].u]||!use[side[i].v])continue;
    		int u=found(side[i].u),v=found(side[i].v);
    		if(u!=v)ans2+=side[i].k,fa[u]=v;
    	}
    	write(ans1,' ');write(ans2,'
    ');
    	return 0;
    }
    
  • 相关阅读:
    20140630 科技脉搏-互联网精神之“我不是为了输赢,我就是认真”
    iOS 获取本地视频的缩略图
    iOS App与iTunes文件传输的方法和对iOS App文件结构的说明
    罗振宇自媒体品牌“罗辑思维”估值1亿背后:媒体通往社群之路
    20140622 科技脉搏 -互联网思维之“一群人团结起来占其他人便宜”
    20140616 科技脉搏 -最大颠覆来自创业公司与边缘产业
    关于流媒体(m3u8)的下载与播放
    20140608 科技脉搏 -下半身需求是人类共同需求,有多少人就有多大市场
    IOS遍历未知对象属性、函数
    iOS中使用 Reachability 检测网络
  • 原文地址:https://www.cnblogs.com/hongyj/p/9285855.html
Copyright © 2020-2023  润新知