20 分代码:
#include<iostream>
#include<cstring>
#include<algorithm>
#include<map>
#include<vector>
#include<queue>
#include<cmath>
#include<unordered_map>
using namespace std;
//char buf[1<<20], *p1=buf, *p2=buf;
//#define getchar() (p1==p2&&(p2=buf+fread(p1=buf, 1, 1<<20, stdin), p1==p2)?EOF:*p1++)
template <typename T>
void read(T &x)
{
x=0;int f=1;char c=getchar();
while (!isdigit(c)) f=(c=='-')?-1:1, c=getchar();
while (isdigit(c)) x=(x<<1)+(x<<3)+c-'0', c=getchar();
x*=f;
}
typedef long long LL;
const int N=2.5e5+10;
int n, m, tsp, stack[N], top, q[N], dfn[N];LL w[N];
struct edge{int x, y;LL c;int pre;}a[N<<2];int alen, last[N<<1];
void ins(int x, int y, LL c)
{
alen++;a[alen]={x, y, c, last[x]};last[x]=alen;
alen++;a[alen]={y, x, c, last[y]};last[y]=alen;
}
edge G[N<<2];int glen, last_g[N];
void ins_g(int x, int y) {glen++;G[glen].x=x, G[glen].y=y;G[glen].pre=last_g[x];last_g[x]=glen;}
struct trnode{int f, dep, Size, top, son;}tr[N];
void init1(int x, int f)
{
tr[x]={f, tr[f].dep+1, 1, 0, 0};
int maxson=-1;
for (int k=last[x];k;k=a[k].pre)
{
int y=a[k].y;
if (y==f) continue;
w[y]=min(w[x], a[k].c);
init1(y, x);
tr[x].Size+=tr[y].Size;
if (maxson<tr[y].Size) maxson=tr[y].Size, tr[x].son=y;
}
}
void init2(int x, int top)
{
tr[x].top=top;
dfn[x]=++tsp;
if (!tr[x].son) return ;
init2(tr[x].son, top);
for (int k=last[x];k;k=a[k].pre)
{
int y=a[k].y;
if (y==tr[x].f||y==tr[x].son) continue ;
init2(y, y);
}
}
int LCA(int x, int y)
{
while (tr[x].top!=tr[y].top)
{
if (tr[tr[x].top].dep>tr[tr[y].top].dep) x=tr[tr[x].top].f;
else y=tr[tr[y].top].f;
}
return tr[x].dep<tr[y].dep?x:y;
}
bool v[N];
LL trdp(int x)
{
// cerr<<1<<endl;
if (!last_g[x]) return w[x];
LL res=0;
for (int k=last_g[x];k;k=G[k].pre)
res+=trdp(G[k].y);
last_g[x]=0;v[x]=0;
return min(w[x], res);
}
bool cmp(int n1, int n2) {return dfn[n1]<dfn[n2];}
int main()
{
memset(last_g, 0, sizeof last_g);
memset(w, 0x3f, sizeof w);
read(n);
for (int i=1;i<n;i++)
{
int x, y;LL c;
read(x), read(y), read(c);
ins(x, y, c);
}
init1(1, 0);init2(1, 1);
read(m);glen=0;
for (int t=1;t<=m;t++)
{
int k;read(k);
for (int i=1;i<=k;i++) read(q[i]);
sort(q+1, q+k+1, cmp);stack[top=1]=1;
if (q[1]!=1) stack[++top]=q[1];
for (int i=2, lca;i<=k;i++)
{
lca=LCA(stack[top], q[i]);
while (top>1&&tr[lca].dep<=tr[stack[top-1]].dep) ins_g(stack[top-1], stack[top]), top--;
if (stack[top]!=lca)
{
ins_g(lca, stack[top]);
if (stack[top-1]==lca) top--;
else stack[top]=lca;
}
stack[++top]=q[i];
}
while (top>1)
ins_g(stack[top-1], stack[top]), top--;
// cerr<<1<<endl;
printf("%lld\n", trdp(1)), glen=0;
// cerr<<1<<endl;
}
return 0;
}
100 分代码:
#include<iostream>
#include<cstring>
#include<algorithm>
#include<map>
#include<vector>
#include<queue>
#include<cmath>
#include<unordered_map>
using namespace std;
//char buf[1<<20], *p1=buf, *p2=buf;
//#define getchar() (p1==p2&&(p2=buf+fread(p1=buf, 1, 1<<20, stdin), p1==p2)?EOF:*p1++)
template <typename T>
void read(T &x)
{
x=0;int f=1;char c=getchar();
while (!isdigit(c)) f=(c=='-')?-1:1, c=getchar();
while (isdigit(c)) x=(x<<1)+(x<<3)+c-'0', c=getchar();
x*=f;
}
typedef long long LL;
const int N=2.5e5+10;
int n, m, tsp, stack[N], top, q[N], dfn[N];LL w[N];
struct edge{int x, y;LL c;int pre;}a[N<<2];int alen, last[N<<1];
void ins(int x, int y, LL c)
{
alen++;a[alen]={x, y, c, last[x]};last[x]=alen;
alen++;a[alen]={y, x, c, last[y]};last[y]=alen;
}
edge G[N<<2];int glen, last_g[N];
void ins_g(int x, int y) {glen++;G[glen].x=x, G[glen].y=y;G[glen].pre=last_g[x];last_g[x]=glen;}
struct trnode{int f, dep, Size, top, son;}tr[N];
void init1(int x, int f)
{
tr[x]={f, tr[f].dep+1, 1, 0, 0};
int maxson=-1;
for (int k=last[x];k;k=a[k].pre)
{
int y=a[k].y;
if (y==f) continue;
w[y]=min(w[x], a[k].c);
init1(y, x);
tr[x].Size+=tr[y].Size;
if (maxson<tr[y].Size) maxson=tr[y].Size, tr[x].son=y;
}
}
void init2(int x, int top)
{
tr[x].top=top;
dfn[x]=++tsp;
if (!tr[x].son) return ;
init2(tr[x].son, top);
for (int k=last[x];k;k=a[k].pre)
{
int y=a[k].y;
if (y==tr[x].f||y==tr[x].son) continue ;
init2(y, y);
}
}
int LCA(int x, int y)
{
while (tr[x].top!=tr[y].top)
{
if (tr[tr[x].top].dep>tr[tr[y].top].dep) x=tr[tr[x].top].f;
else y=tr[tr[y].top].f;
}
return tr[x].dep<tr[y].dep?x:y;
}
bool v[N];
LL trdp(int x)
{
// cerr<<1<<endl;
if (!last_g[x]) return w[x];
LL res=0;
for (int k=last_g[x];k;k=G[k].pre)
res+=trdp(G[k].y);
last_g[x]=0;v[x]=0;
return min(w[x], res);
}
bool cmp(int n1, int n2) {return dfn[n1]<dfn[n2];}
int main()
{
memset(last_g, 0, sizeof last_g);
memset(w, 0x3f, sizeof w);
read(n);
for (int i=1;i<n;i++)
{
int x, y;LL c;
read(x), read(y), read(c);
ins(x, y, c);
}
init1(1, 0);init2(1, 1);
read(m);glen=0;
for (int t=1;t<=m;t++)
{
int k;read(k);
for (int i=1;i<=k;i++) read(q[i]);
sort(q+1, q+k+1, cmp);stack[top=1]=1;
if (q[1]!=1) stack[++top]=q[1];
for (int i=2, lca;i<=k;i++)
{
lca=LCA(stack[top], q[i]);
if (lca==stack[top]) continue;
while (top>1&&tr[lca].dep<=tr[stack[top-1]].dep) ins_g(stack[top-1], stack[top]), top--;
if (stack[top]!=lca)
{
ins_g(lca, stack[top]);
if (stack[top-1]==lca) top--;
else stack[top]=lca;
}
stack[++top]=q[i];
}
while (top>1)
ins_g(stack[top-1], stack[top]), top--;
// cerr<<1<<endl;
printf("%lld\n", trdp(1)), glen=0;
// cerr<<1<<endl;
}
return 0;
}
加了在建虚树时判断 lca 是否等于当前栈顶,如果是则 continue。一般来说应该不用加这句话,为什么这里要加。