- 給出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;
}