F
给你ABC三个串 让你求D串
D是AB的子序列 C是D的子串
求D的长度
求出C在AB中出现的位子记录开始位子和结束位子
n^2 枚举在A中位子和在B中位子
然后得到AB 开始位子之前的lcs 和AB结束位子的lcs
开始预处理一下lcs
#include#include #include #include
D
n个点n-1条边 你只可以去掉一条 花费是 这条边的权 * (块里面最大的距离) 要求这个最小
显然这个和树的直径有关 那么先2遍dfs求树的直径
然后枚举每条边 1 这条边在直径上 那么要求的就是边两端点对应的子树的最大深度
2 不在直径上 那么就是边权*直径
#include#include #include using namespace std;#define inf 2e9+7#define MAXN 100010int head[MAXN];struct node{ int v,w,next,id;}edge[MAXN<<1];int ds[MAXN],dt[MAXN],cnt,ms[MAXN],mt[MAXN];void add(int u,int v,int w,int id){ edge[cnt].id=id; edge[cnt].v=v; edge[cnt].w=w; edge[cnt].next=head[u]; head[u]=cnt++;}void dfs(int u,int fa){ for(int i=head[u];i!=-1;i=edge[i].next) { int v=edge[i].v; if(v==fa) continue; ds[v]=ds[u]+1; dfs(v,u); }}void dfs1(int u,int fa){ for(int i=head[u];i!=-1;i=edge[i].next) { int v=edge[i].v; if(v==fa) continue; dt[v]=dt[u]+1; dfs1(v,u); }}void dfs2(int u,int fa){ mt[u]=dt[u]; for(int i=head[u];i!=-1;i=edge[i].next) { int v=edge[i].v; if(v==fa) continue; dfs2(v,u); mt[u]=max(mt[u],mt[v]); }}void dfs3(int u,int fa){ ms[u]=ds[u]; for(int i=head[u];i!=-1;i=edge[i].next) { int v=edge[i].v; if(v==fa) continue; dfs3(v,u); ms[u]=max(ms[u],ms[v]); }}int id,ans,len;void dfs4(int u,int fa){ for(int i=head[u];i!=-1;i=edge[i].next) { int v=edge[i].v; if(v==fa) continue; if(ds[u]+dt[v]+1==len) { if(max(ms[u],mt[v])*edge[i].w ds[s]) s=i; ds[s]=0; dfs(s,-1); int tt=1; len=ds[1]; for(int i=1;i<=n;i++) if(ds[i]>ds[tt]) { tt=i; len=ds[i]; } dt[tt]=0; dfs1(tt,-1); dfs2(s,-1); dfs3(tt,-1); ans=inf; dfs4(s,-1); printf("Case #%d: %d\n",ca++,id); } return 0;}