2015 Multi-University Training Contest 3 || HDU 5325 Crazy Bobo || 类似bfs

来源:互联网 发布:ubuntu服务器密码修改 编辑:程序博客网 时间:2024/06/01 10:44

hdu 5325 Crazy Bobo
题意:

  • 给出n个带有权值w[i]的点,n-1条边,一棵以x为根的子树,这棵子树是满足每一条路径中包含x,其中x的权值最小,且这条路径的权值是单调递增的。求所有x子树中包含点的数目最多的点数。

思路:

  • 这里写图片描述

  • 官方题解好简单,几句话就搞定了,按照这个思路,我先做好了预处理,然后bfs,然后就是tle无数。最后才明白,有个类似(tm就是累死)。仔细想了想,其实纯bfs是有很多多余的操作(如果数据给力的话,当然实际也给力,不然也不会tle了),看了标程后,。。。直接对边中点权值较大的计数,然后直接通过计数的次数来进行bfs,节省了很多的计算步骤。这个是真心没想到。

时间复杂度:

  1. O(n)

不多说,上代码:

/* ***********************************************Author        :IlovezilianCreated Time  :2015/7/29 9:59:15File Name     :1010.cpp ************************************************ */#include <bits/stdc++.h>#define fi(i,n) for(int i = 0; i < n; i ++)#define fin(i,n1,n2) for(int i = n1; i < n2; i ++)#define ll long long#define INF 0x0x7fffffffusing namespace std;const int N = 500050, mod = 1e9+7;int W[N];vector<int> e[N];int n, ans, cnt[N],vis[N];void bfs(){    queue<int > q;    fin(i,1,n+1) if(!vis[i]) q.push(i);    ans = 0;    while(!q.empty())    {        int u = q.front(); q.pop();        ans = max(ans, cnt[u]);        for(int j = 0; j < e[u].size(); j ++)        {            int v = e[u][j];            cnt[v] += cnt[u];            vis[v] --;            if(vis[v] == 0) q.push(v);        }    }}int main(){    std::ios::sync_with_stdio(false);    std::cin.tie(0);    //freopen("1010.in","r",stdin);    //freopen("my.out","w",stdout);    while(cin>>n)    {        fill(cnt + 0, cnt + n + 1, 1);        memset(vis, 0, sizeof(vis));        fi(i, n + 1) e[i].clear();        fi(i,n) cin>>W[i+1];        int x, y;        fi(i,n-1)         {            cin>>x>>y;            if(W[x] > W[y]) e[x].push_back(y), vis[y] ++;            else e[y].push_back(x), vis[x] ++;        }        bfs();        //fin(i,1, n + 1) printf("cnt[%d] = %d\n", i, cnt[i]);        cout<<ans<<'\n';        cout<<flush;    }//  printf("Time used = %.2f\n", (double) clock() / CLOCKS_PER_SEC);    return 0;}

超时代码:

/* ***********************************************Author        :IlovezilianCreated Time  :2015/7/29 9:59:15File Name     :1010.cpp************************************************ */#include <bits/stdc++.h>#define fi(i,n) for(int i = 0; i < n; i ++)#define fin(i,n1,n2) for(int i = n1; i < n2; i ++)#define ll long long#define INF 0x0x7fffffffusing namespace std;const int N = 500050, mod = 1e9+7;pair<int, int> pr[N];vector<int> e[N];bool vis[N];int n, ans, cnt[N];void bfs(){    memset(vis, 0, sizeof(vis));    ans = 0;    queue<int > q;    for(int i = 0; i < n; i ++) if(!vis[pr[i].second])    {        while(!q.empty()) q.pop();        int u = pr[i].second, cnt = 1;        q.push(u);        vis[u] = 1;        //printf("%d\n", q.empty());        //printf("u = %d\n", u);        while(!q.empty())        {            for(int j = 0; j < e[u].size(); j ++)            {                int v = e[u][j];                q.push(v);                vis[v] = 1;            }            cnt += e[u].size();        //  printf("u1 = %d\n", u);            q.pop();            u = q.front();        }        ans = max(ans, cnt);    }    return ;}int main(){    std::ios::sync_with_stdio(false);    std::cin.tie(0);   // freopen("1010.in","r",stdin);    //freopen("my.out","w",stdout);    //printf("Time = %.2f\n", (double) clock() / CLOCKS_PER_SEC);    time_t st, ed, t;    while(cin>>n)    {        fi(i, n + 1) e[i].clear();        int w;        fi(i,n)         {            cin>>w;            pr[i] = make_pair(w, i+1);        }        int x, y;        fi(i,n-1)         {            cin>>x>>y;            if(pr[x-1].first < pr[y-1].first) e[x].push_back(y);            else e[y].push_back(x);        }/*        fin(i,1,n+1)        {            printf("e[%d] = ", i);            fi(j,e[i].size()) printf(" %d ", e[i][j]);             puts("");        }*/        sort(pr, pr + n);        //fi(i,n) printf("pair[%d].first = %d pair[%d].second = %d\n", i, pr[i].first, i, pr[i].second);        bfs();        cout<<ans<<'\n';    }    //printf("Time used = %.2f\n", (double) clock() / CLOCKS_PER_SEC);    return 0;}
0 0