首页 > 其他分享 >1036 [SCOI2012]滑雪与时间胶囊 最小生成树 可以用prim做的DAG prim+kruskal不能做DAG的原因

1036 [SCOI2012]滑雪与时间胶囊 最小生成树 可以用prim做的DAG prim+kruskal不能做DAG的原因

时间:2022-08-20 21:12:38浏览次数:141  
标签:DAG prim int kruskal st 景点 dist define

链接:https://ac.nowcoder.com/acm/contest/26077/1036
来源:牛客网

题目描述

a180285非常喜欢滑雪。他来到一座雪山,这里分布着M条供滑行的轨道和N个轨道之间的交点(同时也是景点),而且每个景点都有一编号i(1 ≤ i ≤ N)和一高度Hi。a180285 能从景点i 滑到景点j 当且仅当存在一条i 和j 之间的边,且i 的高度不小于j。  与其他滑雪爱好者不同,a180285喜欢用最短的滑行路径去访问尽量多的景点。如果仅仅访问一条路径上的景点,他会觉得数量太少。于是a180285拿出了他随身携带的时间胶囊。  这是一种很神奇的药物,吃下之后可以立即回到上个经过的景点(不用移动也不被认为是 a180285 滑行的距离)。 请注意,这种神奇的药物是可以连续食用的,即能够回到较长时间 之前到过的景点(比如上上个经过的景点和上上上个经过的景点)。  现在,a180285站在1号景点望着山下的目标,心潮澎湃。他十分想知道在不考虑时间 胶囊消耗的情况下,以最短滑行距离滑到尽量多的景点的方案(即满足经过景点数最大的前 提下使得滑行总距离最小)。你能帮他求出最短距离和景点数吗?

输入描述:

输入的第一行是两个整数N,M。 接下来1行有N个整数Hi,分别表示每个景点的高度。 接下来M行,表示各个景点之间轨道分布的情况。每行3个整数,Ui,Vi,Ki。表示编号为Ui的景点和编号为Vi的景点之间有一条长度为Ki的轨道。

输出描述:

输出一行,表示a180285最多能到达多少个景点,以及此时最短的滑行距离总和。
示例1

输入

复制
3 3 
3 2 1 
1 2 1 
2 3 1 
1 3 10

输出

复制
3 2

备注:

对于30% 的数据,1≤n≤20001 \le n \le 20001≤n≤2000;
对于100% 的数据,1≤n≤1051 \le n \le 10^51≤n≤105。

对于所有的数据,保证 1≤m≤1061 \le m \le 10^61≤m≤106 , 1≤hi≤1091 \le h_i \le 10^91≤hi​≤109 ,1≤ki≤1091 \le k_i \le 10^91≤ki​≤109。

分析

题目要求:到达的点数最多,并要求路径最短。

由于有时空胶囊的存在,从1号点能到达的点都是能到达的。

问题就变成了 从1号点 能到达的所有点所生成的最小生成树。

对于高度相同的点之间是无向边,高度高的点向高度低的点有有向边。

 

 

kruskal算法不能跑DAG的原因:无法确定每个被有向边连接到集合的点,都能通过其它有向边到达。
prim算法不能跑DAG的原因:无法确定当前选择的集合,通过有向边扩展到其它点的路径是最优的。

本题不能用kruskal算法的原因:如上,无法确定每个点都是如何被扩展的。可能有些点是无法到达的。
本题能用prim算法的原因:prim能到达的点都是确定能到达的,且本题同层的节点都是无向边,只有上层到下层是有向边,但是下层不能到达上册
可以下层到上层可以看成是距离无穷的有向边,这些边被选中也不会使路径更短,这样其实每条边都可以看成是无向边,也就从有向图转移成无向图了。

 

prim可以是部分有向图(有向图的相对边可以看成无穷大才行)

kruskal只能是无向图(就算看成无穷大,但是有些点它到不了也会连进去。)

 

至于起点,直接从1号点开始跑就可以了。

 

//-------------------------代码----------------------------

#define int ll
const int N = 1e5+10,M = 2e6+10;
int e[M],ne[M],w[M],h[N],idx;
int n,m;

void add(int a,int b,int c) {
    e[idx] = b,ne[idx] = h[a],w[idx] = c,h[a] = idx ++ ;
}
int st;

struct node {
    int id,h,dis;
    bool operator<(const node&x) const {
        if(h == x.h) return dis>x.dis;
        return h < x.h;
    }
};
node p[N];
int dist[N],ans = 0,cnt = 0;
bool vis[N];
void prim() {
    st = 1;
    priority_queue<node> q;
    ms(dist,0x3f);
    ms(vis,0);
    dist[st] = 0;
    q.push({st,p[st].h,p[st].dis});
    while(q.size()) {
        auto tmp = q.top();q.pop();
        int ver = tmp.id;
        if(vis[ver]) continue;
        vis[ver] = 1;
        cnt ++ ;ans += dist[ver];
        int cnt = 0;
        fe(i,ver) {
            int j = e[i];
            if(vis[j]) continue;
            if(dist[j] > w[i])  {
                dist[j] = w[i];
                p[j].dis = w[i];
                if(!vis[j]) q.push({j,p[j].h,dist[j]});
            }
        }
    }
}

void solve()
{
    cin>>n>>m;
    int mx = 0;
    ms(h,-1);
    fo(i,1,n) {
        cin>>p[i].h;
        p[i].dis = inf;
        if(p[i].h > mx) {
            mx = max(mx,p[i].h);
            st = i;
        }
    }
    p[st].dis = 0;
    fo(i,1,m) {
        int u,v,w;
        cin>>u>>v>>w;
        if(p[u].h >= p[v].h)add(u,v,w);
        if(p[v].h >= p[u].h)add(v,u,w);
    }
    prim();
    cout<<cnt<<' '<<ans<<endl;
}
void main_init() {}
signed main(){
    AC();clapping();TLE;
    cout<<fixed<<setprecision(12);
    main_init();
//  while(cin>>n,n)
//  while(cin>>n>>m,n,m)
//    int t;cin>>t;while(t -- )
    solve();
//    {solve(); }
    return 0;
}

/*样例区


*/

//------------------------------------------------------------

 

#include<bits/stdc++.h>#define TLE ios::sync_with_stdio(0),cin.tie(0)#define endl "\n"#define FILE "a"#define pb push_back#define gg exit(0);#define rt return;#define bd cout<<"debug"<<endl;#define db(x) cout<<#x<<':'<<x<<endl;#define dbb(i,a) cout<<#i<<':'<<i<<' '<<#a<<':'<<a<<' '<<endl;#define dbbb(i,a,b) cout<<#i<<':'<<i<<' '<<#a<<':'<<a<<' '<<#b<<':'<<b<<endl;#define TIME cout<<"RuningTime: "<<clock()<<"ms\n";#define YES cout<<"YES"<<endl;#define Yes cout<<"Yes"<<endl;#define NO cout<<"NO"<<endl;#define No cout<<"No"<<endl;#define None cout<<-1<<endl;#define el cout<<endl;#define x first#define y second#define V vector#define fo(i,j,n) for(int i = j;i<=n;i++)#define of(i,n,j) for(int i = n;i>=j;i--)#define fe(i,u) for(int i = h[u];~i;i=ne[i])#define all(a) a.begin(),a.end()#define alll(a) a.begin()+1,a.end()#define ms(a,b) memset(a, b, sizeof(a));#define tr_len(u) (tr[u].r - tr[u].l + 1)#define tr_mid (tr[u].l + tr[u].r >> 1)#define ul (u<<1)#define ur (u<<1|1)#define lowbit(x) (x&-x)#define gcd(a,b) __gcd(a,b)#define CLAP 11243using namespace std;void clapping() {#if CLAP == 1srand(time(NULL)+rand());freopen("a.in","r",stdin);freopen("a.out","w",stdout);//freopen("a.in","w",stdout);#endif}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<<1)+(res<<3)+(c^48);res*=flag;}typedef pair<int,int> pii;typedef pair<long,long>pll;typedef long long ll;const int inf = 0x3f3f3f3f;const ll INF = 0x3f3f3f3f3f3f3f3fll;const double eps = 1e-8;int dy[] = {1,0,-1,0,1,1,-1,-1};int dx[] = {0,1,0,-1,1,-1,1,-1};template<class T> T qmi(T a,T b,T p) {T res = 1;for(;b;b>>=1,a=1ll*a*a%p)if(b&1)res = 1ll*res*a%p;return res;}template<class T> T exgcd(T a,T b,T &x,T &y) {if(b == 0) {x = 1;y = 0;return a;}ll d = gcd_ed(b,a%b,y,x);y = y - a / b * x;return d;}template<class T> T qmul(T a,T b,T p) {T res = 0;for(;b;b >>= 1,a = (a + a) % p) {res = (res + a) % p;}return res;}/*文档区

*/void AC(){    ////                       _oo0oo_//                      o8888888o//                      88" . "88//                      (| -_- |)//                      0\  =  /0//                    ___/`---'\___//                  .' \\|     |// './/                 / \\|||  :  |||// \//                / _||||| -:- |||||- \//               |   | \\\  -  /// |   |//               | \_|  ''\---/''  |_/ |//               \  .-\__  '-'  ___/-. ///             ___'. .'  /--.--\  `. .'___//          ."" '<  `.___\_<|>_/___.' >' "".//         | | :  `- \`.;`\ _ /`;.`/ - ` : | |//         \  \ `_.   \_ __\ /__ _/   .-` /  ///     =====`-.____`.___ \_____/___.-`___.-'=====//                   佛祖保佑, 永无bug;}

//-------------------------代码----------------------------
#define int llconst int N = 1e5+10,M = 2e6+10;int e[M],ne[M],w[M],h[N],idx;int n,m;
void add(int a,int b,int c) {    e[idx] = b,ne[idx] = h[a],w[idx] = c,h[a] = idx ++ ;}int st;
struct node {    int id,h,dis;    bool operator<(const node&x) const {        if(h == x.h) return dis>x.dis;        return h < x.h;    }};node p[N];int dist[N],ans = 0,cnt = 0;bool vis[N];void prim() {    st = 1;    priority_queue<node> q;    ms(dist,0x3f);    ms(vis,0);    dist[st] = 0;    q.push({st,p[st].h,p[st].dis});    while(q.size()) {        auto tmp = q.top();q.pop();        int ver = tmp.id;        if(vis[ver]) continue;        vis[ver] = 1;        cnt ++ ;ans += dist[ver];        int cnt = 0;        fe(i,ver) {            int j = e[i];            if(vis[j]) continue;            if(dist[j] > w[i])  {                dist[j] = w[i];                p[j].dis = w[i];                if(!vis[j]) q.push({j,p[j].h,dist[j]});            }        }    }}
void solve(){cin>>n>>m;    int mx = 0;    ms(h,-1);    fo(i,1,n) {        cin>>p[i].h;        p[i].dis = inf;        if(p[i].h > mx) {            mx = max(mx,p[i].h);            st = i;        }    }    p[st].dis = 0;    fo(i,1,m) {        int u,v,w;        cin>>u>>v>>w;        if(p[u].h >= p[v].h)add(u,v,w);        if(p[v].h >= p[u].h)add(v,u,w);    }    prim();    cout<<cnt<<' '<<ans<<endl;}void main_init() {}signed main(){AC();clapping();TLE;cout<<fixed<<setprecision(12);main_init();//  while(cin>>n,n)//  while(cin>>n>>m,n,m)//int t;cin>>t;while(t -- )solve();//{solve(); }return 0;}
/*样例区

*/
//------------------------------------------------------------



标签:DAG,prim,int,kruskal,st,景点,dist,define
From: https://www.cnblogs.com/er007/p/16608612.html

相关文章

  • C++primer练习16.1-14
    练习16.1::实例化就是模板通过实际调用而确定类型及其运算,抽象到具体练习16.2template<typenameT>intcompare(constT&v1,constT&v2){if(v1<v2)return-1;......
  • C++primer练习15.15-33
    练习15.15重新定义Bulk_quoteclassDisc_quote:publicQuote{public:Disc_quote()=default;Disc_quote(conststd::string&book,doublep......
  • C++primer练习15.1-14
    练习15.1什么是虚成员?::需要派生类自己定义的成员练习15.2protected访问说明符与private有何区别?::protected允许派生类访问,private一律不允许访问练习15.3定义你自己的......
  • 「学习笔记」Kruskal 重构树
    前置芝士:最小生成树、Kruskal算法、瓶颈(图上路径最值)正文定义在执行Kruskal算法的过程中我们会从小到大加入若干条边,现在我们仍然按照这个顺序。首先新建\(n\)个......
  • C++primer练习14.44-53
    练习14.44编写一个简单的桌面计算器使其处理二元计算doubleadd(doublea,doubleb){returna+b;}autosubtra=[](doublea,doubleb){returna-b;};stru......
  • 1009 Forsaken喜欢独一无二的树 删边找唯一kruskal生成树
     链接:https://ac.nowcoder.com/acm/contest/26077/1009来源:牛客网题目描述       众所周知,最小生成树是指使图中所有节点连通且边......
  • C++primer练习14.26
    练习14.26为你的String类定义下标运算符char&operator[](size_td){returnelements[d];}constchar&operator[](size_td)const......
  • C++primer练习14.10-23
    练习14.10对于Sales_data的输入运算符来说给定下面的输入会发生什么?(a)0-201-99999-91024.95正常输入(b)1024.950-210-99999-9最后一个输入格式错误,会chongz练习14.11......
  • C++primer练习14.1-9
    练习14.1在什么时候情况下重载的运算符与内置运算符有所区别?在什么时候重载的运算符又与内置运算符一样::为类设计的运算符,尽量重载的运算符含义不要改变,如+还是加法练习1......
  • C++primer练习13.55-58
    练习13.55为你的StrBlob添加一个右值引用版本的Push_backvoidStrBlob::push_back(string&&s){data->push_back(std::move(s));}练习13.56如果sorted定义如下,会发生......