社区讨论
90ptsWA on #6 对拍了1w+组无果 码风良好 求调
P2495【模板】虚树 / [SDOI2011] 消耗战参与者 1已保存回复 0
讨论操作
快速查看讨论及其快照的属性,并进行相关操作。
- 当前回复
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @mjzr2weh
- 此快照首次捕获于
- 2026/01/04 21:11 2 个月前
- 此快照最后确认于
- 2026/01/08 16:45 上个月
my code
CPP#include<iostream>
#include<vector>
#include<algorithm>
#define int long long
using namespace std;
int read(){
int k=0,f=1;
char c=getchar();
while(c<'0'||c>'9'){
if(c=='-')f=-1;
c=getchar();
}
while(c>='0'&&c<='9')k=k*10+c-'0',c=getchar();
return k*f;
}
const int N=5e6+50,inf=1e18;
vector< pair<int,int> >g[N];
int n,m,cost[N],dfn[N];
bool iskey[N];
namespace sep{
int fa[N],dep[N],siz[N],top[N],son[N],rkn[N],idx;
void dfs1(int u,int f){
fa[u]=f,dep[u]=dep[f]+1,siz[u]=1;
for(auto v:g[u]){
if(v.first==f){
cost[u]=min(cost[f],v.second);
continue;
}
dfs1(v.first,u);
siz[u]+=siz[v.first];
if(siz[v.first]>siz[son[u]])son[u]=v.first;
}
}
void dfs2(int u,int ftop){
top[u]=ftop,dfn[u]=++idx,rkn[idx]=u;
if(son[u]==0)return;
dfs2(son[u],ftop);
for(auto v:g[u]){
if(v.first!=son[u]&&v.first!=fa[u]){
dfs2(v.first,v.first);
}
}
}
int lca(int u,int v){
while(top[u]!=top[v]){
if(dep[top[u]]<dep[top[v]])swap(u,v);
u=fa[top[u]];
}
return (dep[u]<dep[v])?u:v;
}
}
bool cmp(int x,int y){
return dfn[x]<dfn[y];
}
vector<int>h[N];
int sta[N],len,k,key[N];
int f[N];
void print(int x){
cout<<x<<':';
for(auto v:h[x]){
cout<<v<<' ';
}
cout<<endl;
for(auto v:h[x]){
print(v);
}
}
void build(){
for(int i=1;i<=k;i++){
iskey[key[i]]=false;
}
k=read();
for(int i=1;i<=k;i++){
key[i]=read();
iskey[key[i]]=true;
}
//init
len=0,sta[++len]=1;h[1].clear();
sort(key+1,key+1+k,cmp);
for(int i=1;i<=k;i++){
int l=sep::lca(sta[len],key[i]);
if(l!=sta[len]){
while(dfn[l]<dfn[sta[len-1]]){
h[sta[len-1]].push_back(sta[len]),len--;
}
if(dfn[l]>dfn[sta[len-1]]){
h[l].clear();//第一次入栈,清空
h[l].push_back(sta[len]);//连边
sta[len]=l;//弹栈顶并将LCA入栈
}else{//此时l=sta[len-1]
h[l].push_back(sta[len]);//连边
len--;
}
}
sta[++len]=key[i];
h[key[i]].clear();
}
for(int i=1;i<len;i++){
h[sta[i]].push_back(sta[i+1]);
}
}
int dp(int u){
if(iskey[u])return f[u]=cost[u];
int tot=0;
for(auto v:h[u]){
tot+=dp(v);
}
return f[u]=min(cost[u],tot);
}
signed main(){
n=read();
for(int i=1;i<=n-1;i++){
int u=read(),v=read(),w=read();
g[u].push_back(make_pair(v,w));
g[v].push_back(make_pair(u,w));
}
cost[1]=inf;
sep::dfs1(1,0);
sep::dfs2(1,1);
m=read();
for(int i=1;i<=m;i++){
build();
printf("%lld\n",dp(1));
}
return 0;
}
make.cpp
CPP#include<iostream>
#include<time.h>
#include<vector>
#include<string.h>
using namespace std;
int rd(int l,int r){
return l+rand()%(r-l+1);
}
int idx=1;
int main(){
srand(time(NULL));
int n=10000,m=10;
cout<<n<<endl;
for(int i=1;i<=n-1;i++){
cout<<rd(1,idx)<<' '<<idx+1<<' '<<rd(1,1e5)<<endl;
idx++;
}
cout<<m<<endl;
for(int i=1;i<=m;i++){
int k=rd(1,n-1);
cout<<k<<' ';
vector<int>arr(n+1);
for(int i=1;i<=n;i++)arr[i]=i;
for(int i=1;i<=n;i++)swap(arr[rd(1,n)],arr[rd(1,n)]);
for(int i=1;i<=k;i++){
if(arr[i]!=1)cout<<arr[i]<<' ';
else k++;
}
cout<<endl;
}
return 0;
}
题解区搞的题解
CPP#include <bits/stdc++.h>
#define INL inline
#define REG register
#define DB double
#define LDB long double
#define ULL unsigned long long
#define LL long long
#define RPT(i,x,y) for (REG int i=x;i<y;i++)
#define DRPT(i,x,y) for (REG int i=x;i>y;i--)
#define MST(a,b) memset(a,b,sizeof(a))
#define MAXN 500500
#define MAXM 10000
#define MOD 998244353
#define INF 0x3f3f3f3f
#define LLINF 0x3f3f3f3f3f3f3f3f
#define EPS 1e-5
#define _ 0
using namespace std;
int dfn[MAXN];
int dep[MAXN];
int fa[MAXN][25];
LL minv[MAXN];
int m[MAXN];
int lst[MAXN];
bool query[MAXN];
int n,q;
int num;
int top;
int dfscnt=1;
int stak[MAXN];
struct EDGE
{
int to,next;
LL val;
}edge[MAXN<<1],edge1[MAXN<<1];
int head[MAXN];//初始图存储
int cnt=1;
INL void add(int x,int y,LL v)
{
edge[cnt].next=head[x];
edge[cnt].to=y;
edge[cnt].val=v;
head[x]=cnt++;
}
int head1[MAXN];//虚树存储
int cnt1=1;
INL void add1(int x,int y)
{
edge1[cnt1].next=head1[x];
edge1[cnt1].to=y;
head1[x]=cnt1++;
}
void dfs(int pos)
{
int k;
for (k=0;fa[pos][k];k++)
fa[pos][k+1]=fa[fa[pos][k]][k];
m[pos]=k;
dfn[pos]=dfscnt++;
for (int i=head[pos];i;i=edge[i].next)
{
REG int to=edge[i].to;
if (!dfn[to])
{
dep[to]=dep[pos]+1;
minv[to]=min(minv[pos],edge[i].val);
fa[to][0]=pos;
dfs(to);
}
}
}
LL dfs1(int pos) //dp
{
LL sum=0;
LL tem;
for (int i=head1[pos];i;i=edge1[i].next)
{
int to=edge1[i].to;
sum+=dfs1(to);
}
if (query[pos])
tem=minv[pos];
else
tem=min(minv[pos],sum);
query[pos]=false; //清空虚树
head1[pos]=0;
return tem;
}
int lca(int x,int y) //倍增LCA
{
if (dep[x]<dep[y])
swap(x,y);
DRPT(i,m[x],-1)
if (dep[fa[x][i]]>=dep[y])
x=fa[x][i];
if (x==y)
return x;
DRPT(i,m[x],-1)
if (fa[x][i]!=fa[y][i])
{
x=fa[x][i];
y=fa[y][i];
}
return fa[x][0];
}
bool cmp(int x1,int x2)
{
return dfn[x1]<dfn[x2];
}
int main()
{
minv[1]=LLINF;
cin>>n;
int x,y;
LL v;
RPT(i,0,n-1)
{
scanf("%d%d%lld",&x,&y,&v);
add(x,y,v);
add(y,x,v);
}
dfs(1);
cin>>q;
while (q--)
{
cin>>num;
RPT(i,1,num+1)
{
scanf("%d",&lst[i]);
query[lst[i]]=true;
}
sort(lst+1,lst+num+1,cmp);
stak[top=1]=lst[1];
RPT(i,2,num+1)
{
int now=lst[i];
int lc=lca(now,stak[top]);
while (1)
if (dep[lc]>=dep[stak[top-1]])
{
if (lc!=stak[top]) //不满足该条件为情况一
{
add1(lc,stak[top]);
if (lc!=stak[top-1]) //情况二
stak[top]=lc;
else //情况三
top--;
}
break;
}
else //情况四
{
add1(stak[top-1],stak[top]);
top--;
}
stak[++top]=now; //最后统一把now压进栈中
}
while (--top)
add1(stak[top],stak[top+1]); //将最右链放进虚树
cout<<dfs1(stak[1])<<endl;
cnt1=1;
}
return ~~(0^_^0);
}
cmp.cpp
CPP#include<iostream>
using namespace std;
int main(){
for(int i=1;i<=10000;i++){
cout<<"#"<<i<<'\n';
system("make.exe>in.txt");
system("run.exe<in.txt>r.txt");
system("tj.exe<in.txt>t.txt");
if(system("fc r.txt t.txt")){
return 0;
}
}
return 0;
}
可能是我对拍的哪里写错了,不然感觉概率有点低。
小范围和大范围的都试过了,用
小范围和大范围的都试过了,用
clock 函数统计时间感觉没问题。回复
共 0 条回复,欢迎继续交流。
正在加载回复...