QOJ.ac
QOJ
ID | 题目 | 提交者 | 结果 | 用时 | 内存 | 语言 | 文件大小 | 提交时间 | 测评时间 |
---|---|---|---|---|---|---|---|---|---|
#808743 | #7961. 一棵树 | xjt05 | WA | 409ms | 59520kb | C++23 | 4.1kb | 2024-12-11 01:01:37 | 2024-12-11 01:01:43 |
Judging History
answer
#include<iostream>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
#include<deque>
#include<cctype>
#include<string.h>
#include<math.h>
#include<time.h>
#include<random>
#include<stack>
#include<string>
//#include<bits/stdc++.h>
#include <unordered_map>
#define ll long long
#define lowbit(x) (x & -x)
#define endl "\n"// 交互题记得删除
using namespace std;
mt19937 rnd(time(0));
const ll mod =2;
const ll p=rnd()%mod;
const ll maxn=5e5+15;
const ll N=5e5+15;
ll ksm(ll x, ll y)
{
ll ans = 1;
while (y)
{
if (y & 1)
{
ans = ans % mod * (x % mod) % mod;
}
x = x % mod * (x % mod) % mod;
y >>= 1;
}
return ans % mod % mod;
}
ll gcd(ll x, ll y)
{
if (y == 0)
return x;
else
return gcd(y, x % y);
}
void fio()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
}
vector<ll>g[505555];
ll n;
ll sz[maxn],mss[maxn];//sz:树大小,mss最大子树大小
vector<int>v;//重心
void dfs(int p ,int fa){//p当前节点,fa父节点
sz[p]=1;mss[p]=0;//这个节点就他自己,树的大小=1,初始没有子节点,mss[]=0
for(auto too:g[p]){
if(too!=fa){//不是1-->2-->1
dfs(too,p);//往下搜
mss[p]=max(mss[p],sz[too]);//本节点最大子树要么不变,要么是子节点树的大小,取max
sz[p]+=sz[too];//树大小+=子节点树大小
}
}
mss[p]=max(mss[p],n-sz[p]);//要么正着,要么倒着
if(mss[p]<=n/2){//rt=mss[p]<mss[rt]?p:rt;也有这种写法,这个时候不能提前返回
v.push_back(p);//最大子树大小不到一半,是重心
}
}
bool vi[500015];
struct node
{
ll x,y,z;
bool operator<(const node&a)const
{
if(x!=a.x)
return x<a.x;
else
return y>a.y;
}
};
priority_queue<node>f;
ll zx[maxn];
void df(ll x,ll fa,ll sd)
{
ll gs=0;
for(auto j:g[x])
{
if(fa==j)continue;
df(j,x,sd+1);
gs++;
}
///cout<<x<<endl;
f.push({sd,gs,x});
}
ll zf[maxn];
void dc(ll x,ll fa)
{
for(auto j:g[x])
{
if(j==fa)continue;
dc(j,x);
zf[x]+=zf[j];
}
if(vi[x])zf[x]++;
}
ll ans=0;
ll us;
void fk(ll x,ll fa)
{
for(auto j:g[x])
{
if(j==fa)continue;
ans+=abs(zf[x]-zf[j]-zf[j]);
zf[j]+=zf[x]-zf[j];
fk(j,x);
zf[j]-=zf[x]-zf[j];
}
return ;
}
// 这份代码默认节点编号从 1 开始,即 i ∈ [1,n],使用vector存图
int d1[N], d2[N], up[N], x1, yz, mini = 1e9; // d1,d2对应上文中的len1,len2
void dfsd(int cur, int fa) { // 求取len1和len2
for (auto nxtn : g[cur]) {
int nxt = nxtn, w = 1; // nxt为这条边通向的节点,val为边权
if (nxt == fa) {
continue;
}
dfsd(nxt, cur);
if (d1[nxt] + w > d1[cur]) { // 可以更新最长链
d2[cur] = d1[cur];
d1[cur] = d1[nxt] + w;
} else if (d1[nxt] + w > d2[cur]) { // 不能更新最长链,但可更新次长链
d2[cur] = d1[nxt] + w;
}
}
}
void dfsu(int cur, int fa) {
for (auto nxtn : g[cur]) {
int nxt = nxtn, w = 1;
if (nxt == fa) {
continue;
}
up[nxt] = up[cur] + w;
if (d1[nxt] + w != d1[cur]) { // 如果自己子树里的最长链不在nxt子树里
up[nxt] = max(up[nxt], d1[cur] + w);
} else { // 自己子树里的最长链在nxt子树里,只能使用次长链
up[nxt] = max(up[nxt], d2[cur] + w);
}
dfsu(nxt, cur);
}
}
void GetTreeCenter() { // 统计树的中心,记为x和y(若存在)
dfsd(1, 0);
dfsu(1, 0);
for (int i = 1; i <= n; i++) {
if (max(d1[i], up[i]) < mini) { // 找到了当前max(len1[x],up[x])最小点
mini = max(d1[i], up[i]);
x1 = i;
yz = 0;
} else if (max(d1[i], up[i]) == mini) { // 另一个中心
yz = i;
}
}
}
int main()
{
fio();
ll k;
cin>>n>>k;
us=k;
for(ll i=1;i<n;i++)
{
ll l,r;
cin>>l>>r;
g[l].push_back(r);
g[r].push_back(l);
}
//dfs(1,0);
//ll z=*v.begin();
GetTreeCenter();
df(x1,0,1);
while(!f.empty())
{
k--;
vi[f.top().z]=1;
f.pop();
if(k==0)
break;
}
dc(1,0);
fk(1,0);
cout<<ans<<endl;
}
详细
Test #1:
score: 0
Wrong Answer
time: 409ms
memory: 59520kb
input:
499991 31473 1 2 2 3 1 4 2 5 4 6 4 7 6 8 4 9 8 10 6 11 9 12 10 13 10 14 1 15 14 16 3 17 14 18 12 19 13 20 11 21 16 22 16 23 20 24 5 25 16 26 18 27 8 28 15 29 27 30 27 31 26 32 21 33 3 34 27 35 33 36 25 37 22 38 11 39 11 40 17 41 25 42 3 43 3 44 2 45 35 46 25 47 5 48 6 49 41 50 42 51 1 52 39 53 14 54...
output:
15734937912
result:
wrong answer 1st lines differ - expected: '15734930984', found: '15734937912'