- 给出n个带有权值w[i]的点,n-1条边,一棵以x为根的子树,这棵子树是满足每一条路径中包含x,其中x的权值最小,且这条路径的权值是单调递增的。求所有x子树中包含点的数目最多的点数。
思路:
官方题解好简单,几句话就搞定了,按照这个思路,我先做好了预处理,然后bfs,然后就是tle无数。最后才明白,有个类似(tm就是累死)。仔细想了想,其实纯bfs是有很多多余的操作(如果数据给力的话,当然实际也给力,不然也不会tle了),看了标程后,。。。直接对边中点权值较大的计数,然后直接通过计数的次数来进行bfs,节省了很多的计算步骤。这个是真心没想到。
时间复杂度:
O(n)
不多说,上代码:
/* ***********************************************
Author :Ilovezilian
Created Time :2015/7/29 9:59:15
File 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 0x0x7fffffff
using 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 :Ilovezilian
Created Time :2015/7/29 9:59:15
File 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 0x0x7fffffff
using 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;
}