生活随笔
收集整理的這篇文章主要介紹了
P1232 [NOI2013] 树的计数
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
…調半天別的東西寫錯了,心力交瘁。
思路還是不會。。
具體就是二分,沒想到,然后再貪心。
一直沒整明白一個數它要往別的樹走的條件是什么,日后研究。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <set>
#include <vector>
#include <queue>#define mid (l+r>>1)
using namespace std
;
typedef long long LL
;
typedef pair
<int,int> PII
;
typedef pair
<LL
,int> PLI
;
const int N
= 5e4+10, mod
=1e9+7;LL fa
[N
][20], le
[N
][20], deep
[N
], D
;
vector
<PII
>G
[N
];
vector
<int> li
;
vector
<LL
>C
, B
, A
;
int P
[N
], k
, n
;
bool dis
[N
];void dfs(int u
, int f
)
{for(int i
= 1;i
< 20;i
++)fa
[u
][i
] = fa
[fa
[u
][i
-1]][i
-1], le
[u
][i
] = le
[u
][i
-1] + le
[fa
[u
][i
-1]][i
-1]; for(auto x
: G
[u
]){int a
= x
.first
;if(a
== f
)continue;fa
[a
][0] = u
; le
[a
][0] = x
.second
;deep
[a
] = deep
[u
] + x
.second
; dfs(a
, u
);}
}int se(int u
, LL len
)
{for(int i
= 19;i
>= 0;i
--)if(le
[u
][i
] <= len
) len
-= le
[u
][i
], u
= fa
[u
][i
];return u
;
}void dfs2(int u
, int fa
)
{if(dis
[u
] || (G
[u
].size() == 1&& u
!= 1)) return ;dis
[u
] = 1;for(auto x
: G
[u
]){int a
= x
.first
;if(a
== fa
)continue;dfs2(a
, u
);dis
[u
] &= dis
[a
]; }return ;
}bool check(LL len
)
{C
.clear(); B
.clear(); A
.clear();
for(int i
= 1;i
<= n
;i
++) dis
[i
] = 0;for(int i
= 1;i
<= k
;i
++) {int x
= se(P
[i
], len
);if(x
== 1) C
.push_back(P
[i
]);else dis
[x
] = 1;}dfs2(1, 0);sort(C
.begin(), C
.end(), [](int a
, int b
){return D
- deep
[a
] < D
- deep
[b
];}) ;for(auto x
: C
){int a
= se(x
, deep
[x
]-1);if(!dis
[a
]&&len
-deep
[x
]<=deep
[a
])dis
[a
] = 1;else A
.push_back(len
- deep
[x
]);}
for(auto i
:li
) if(!dis
[i
]) B
.push_back(deep
[i
]);
sort(B
.begin(), B
.end());sort(A
.begin(), A
.end());int now
= 0, siz
= A
.size();for(auto x
: B
){while(now
!= siz
&& A
[now
] < x
) now
++;if(now
== siz
)return 0;now
++;}return 1;
}int main()
{ scanf("%d", &n
);for(int i
= 2;i
<= n
;i
++){int a
, b
, c
;scanf("%d%d%d", &a
, &b
, &c
);if(a
> b
)swap(a
, b
);G
[a
].push_back({b
, c
});G
[b
].push_back({a
, c
});if(a
== 1) li
.push_back(b
);}for(int i
= 0;i
< 20;i
++) le
[1][i
] = 0x3f3f3f3f3f3f3f3f;dfs(1, 0); sort(li
.begin(), li
.end(), [](int a
, int b
){return deep
[a
] < deep
[b
];});scanf("%d", &k
);for(int i
= 1;i
<= k
;i
++)scanf("%d", P
+i
);LL l
= 0, r
= 1e14; while(l
< r
){if(check(mid
)) r
= mid
;else l
= mid
+1;}if(k
< li
.size()) l
= -1;printf("%lld\n", l
);return 0;
}
總結
以上是生活随笔為你收集整理的P1232 [NOI2013] 树的计数的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。