不懂就问
查看原帖
不懂就问
655407
WisNourx_楼主2024/1/25 12:33

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。一般来说应该不用加这句话,为什么这里要加。

2024/1/25 12:33
加载中...