Day4 樹的直徑、重心以及基環樹
文章目錄
A. POJ 1985 Cow Marathon 樹的直徑-模板
題目
程式碼
樹形DP求樹的直徑
#include<algorithm>
#include<bitset>
#include<cctype>
#include<cerrno>
#include<clocale>
#include<cmath>
#include<complex>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<deque>
#include<exception>
#include<fstream>
#include<functional>
#include<limits>
#include<list>
#include<map>
#include<iomanip>
#include<ios>
#include<iosfwd>
#include<iostream>
#include<istream>
#include<ostream>
#include<queue>
#include<set>
#include<sstream>
#include<stack>
#include<stdexcept>
#include<streambuf>
#include<string>
#include<utility>
#include<vector>
#include<cwchar>
#include<cwctype>
using namespace std;
const int maxn=4e4+10;
template<typename T>inline void read(T &x)
{
x=0;
T f=1,ch=getchar();
while (!isdigit(ch) && ch^'-') ch=getchar();
if (ch=='-') f=-1, ch=getchar();
while (isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48), ch=getchar();
x*=f;
}
int ver[maxn<<1],edge[maxn<<1],Next[maxn<<1],head[maxn],len;
inline void add(int x,int y,int z)
{
ver[++len]=y,edge[len]=z,Next[len]=head[x],head[x]=len;
}
int d[maxn<<1],v[maxn<<1],ans;
inline void dp(int x)
{
v[x]=1;
for (int i=head[x];i;i=Next[i])
{
int y=ver[i];
if (v[y]) continue;
dp(y);
ans=max(ans,d[x]+d[y]+edge[i]);
d[x]=max(d[x],d[y]+edge[i]);
}
}
int main()
{
int n,m;read(n);read(m);
for (int i=1;i<=m;++i)
{
int x,y,z;char s;
read(x);read(y);read(z);
cin>>s;
add(x,y,z),add(y,x,z);
}
dp(1);
printf("%d\n",ans);
return 0;
}
BFS 求樹的直徑
#include<algorithm>
#include<bitset>
#include<cctype>
#include<cerrno>
#include<clocale>
#include<cmath>
#include<complex>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<deque>
#include<exception>
#include<fstream>
#include<functional>
#include<limits>
#include<list>
#include<map>
#include<iomanip>
#include<ios>
#include<iosfwd>
#include<iostream>
#include<istream>
#include<ostream>
#include<queue>
#include<set>
#include<sstream>
#include<stack>
#include<stdexcept>
#include<streambuf>
#include<string>
#include<utility>
#include<vector>
#include<cwchar>
#include<cwctype>
using namespace std;
const int maxn=4e4+10;
template<typename T>inline void read(T &x)
{
x=0;
T f=1,ch=getchar();
while (!isdigit(ch) && ch^'-') ch=getchar();
if (ch=='-') f=-1, ch=getchar();
while (isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48), ch=getchar();
x*=f;
}
int ver[maxn<<1],edge[maxn<<1],Next[maxn<<1],head[maxn],len;
inline void add(int x,int y,int z)
{
ver[++len]=y,edge[len]=z,Next[len]=head[x],head[x]=len;
}
int d[maxn<<1],v[maxn<<1],ans,n,m,point;
inline void bfs(int s)
{
memset(v,0,sizeof(v));
memset(d,0,sizeof(d));
queue<int> q;
v[s]=1;
q.push(s);
while (!q.empty())
{
int x=q.front();
q.pop();
for (int i=head[x];i;i=Next[i])
{
int y=ver[i];
if (!v[y])
{
v[y]=1;
d[y]=d[x]+edge[i];
q.push(y);
}
}
}
ans=0;
for (int i=1;i<=n;++i)
if (d[i]>ans)
{
ans=d[i];
point=i;
}
}
int main()
{
read(n);read(m);
for (int i=1;i<=m;++i)
{
int x,y,z;char s;
read(x);read(y);read(z);
cin>>s;
add(x,y,z),add(y,x,z);
}
bfs(1),bfs(point);
printf("%d\n",ans);
return 0;
}
B. POJ 1849 Two 樹的直徑
題目
程式碼
#include<algorithm>
#include<bitset>
#include<cctype>
#include<cerrno>
#include<clocale>
#include<cmath>
#include<complex>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<deque>
#include<exception>
#include<fstream>
#include<functional>
#include<limits>
#include<list>
#include<map>
#include<iomanip>
#include<ios>
#include<iosfwd>
#include<iostream>
#include<istream>
#include<ostream>
#include<queue>
#include<set>
#include<sstream>
#include<stack>
#include<stdexcept>
#include<streambuf>
#include<string>
#include<utility>
#include<vector>
#include<cwchar>
#include<cwctype>
using namespace std;
const int maxn=4e4+10;
template<typename T>inline void read(T &x)
{
x=0;
T f=1,ch=getchar();
while (!isdigit(ch) && ch^'-') ch=getchar();
if (ch=='-') f=-1, ch=getchar();
while (isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48), ch=getchar();
x*=f;
}
int ver[maxn<<1],edge[maxn<<1],Next[maxn<<1],head[maxn],len;
inline void add(int x,int y,int z)
{
ver[++len]=y,edge[len]=z,Next[len]=head[x],head[x]=len;
}
int d[maxn<<1],v[maxn<<1],ans;
inline void dp(int x)
{
v[x]=1;
for (int i=head[x];i;i=Next[i])
{
int y=ver[i];
if (v[y]) continue;
dp(y);
ans=max(ans,d[x]+d[y]+edge[i]);
d[x]=max(d[x],d[y]+edge[i]);
}
}
int main()
{
int n,m,sum=0;read(n);read(m);
for (int i=1;i<n;++i)
{
int x,y,z;
read(x);read(y);read(z);
add(x,y,z),add(y,x,z);
sum+=z;
}
dp(1);
printf("%d\n",(sum<<1)-ans);
return 0;
}
C. POJ 1655 Balancing Act 樹的重心-模板
題目
程式碼
#include<algorithm>
#include<bitset>
#include<cctype>
#include<cerrno>
#include<clocale>
#include<cmath>
#include<complex>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<deque>
#include<exception>
#include<fstream>
#include<functional>
#include<limits>
#include<list>
#include<map>
#include<iomanip>
#include<ios>
#include<iosfwd>
#include<iostream>
#include<istream>
#include<ostream>
#include<queue>
#include<set>
#include<sstream>
#include<stack>
#include<stdexcept>
#include<streambuf>
#include<string>
#include<utility>
#include<vector>
#include<cwchar>
#include<cwctype>
using namespace std;
const int maxn=2e4+10;
template<typename T>inline void read(T &x)
{
x=0;
T f=1,ch=getchar();
while (!isdigit(ch) && ch^'-') f=-1, ch=getchar();
if (ch=='-') f=-1, ch=getchar();
while (isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48), ch=getchar();
x*=f;
}
int vis[maxn],siz[maxn],ans,pos,n;
int ver[maxn<<1],Next[maxn<<1],head[maxn],len;
inline void add(int x,int y)
{
ver[++len]=y,Next[len]=head[x],head[x]=len;
}
inline void dfs(int x)
{
vis[x]=1,siz[x]=1;
int maxpart=0;
for (int i=head[x];i;i=Next[i])
{
int y=ver[i];
if (!vis[y])
{
dfs(y);
siz[x]+=siz[y];
maxpart=max(maxpart,siz[y]);
}
}
maxpart=max(maxpart,n-siz[x]);
if (maxpart<ans || (maxpart==ans && x<pos))
ans=maxpart,pos=x;
}
int main()
{
int t;read(t);
while (t--)
{
read(n);
memset(vis,0,sizeof(vis));
memset(head,0,sizeof(head));
len=pos=0;
ans=0x3f3f3f3f;
for (int x,y,i=1;i<n;++i)
{
read(x);read(y);
add(x,y);add(y,x);
}
dfs(1);
printf("%d %d\n",pos,ans);
}
return 0;
}
來自Tyouchie的鄰接矩陣寫法
#include<algorithm>
#include<bitset>
#include<cctype>
#include<cerrno>
#include<clocale>
#include<cmath>
#include<complex>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<deque>
#include<exception>
#include<fstream>
#include<functional>
#include<limits>
#include<list>
#include<map>
#include<iomanip>
#include<ios>
#include<iosfwd>
#include<iostream>
#include<istream>
#include<ostream>
#include<queue>
#include<set>
#include<sstream>
#include<stack>
#include<stdexcept>
#include<streambuf>
#include<string>
#include<utility>
#include<vector>
#include<cwchar>
#include<cwctype>
using namespace std;
const int maxn=2e4+10;
const int INF=0x3f3f3f3f;
vector<int>G[maxn];
int son[maxn];
int ans,n,balance,t;
void dfs(int v,int fa)
{
son[v]=1;
int d=G[v].size();
int pre_balance=0;
for (int i=0;i<d;i++)
{
int k=G[v][i];
if (k!=fa)
{
dfs(k,v);
son[v]+=son[k];
pre_balance=max(pre_balance,son[k]);
}
}
pre_balance=max(pre_balance,n-son[v]);
if (pre_balance<balance || (pre_balance==balance&&v<ans))
{
ans=v;
balance=pre_balance;
}
}
int main()
{
cin>>t;
while (t--)
{
scanf("%d",&n);
for (int i=1;i<=n;++i)
G[i].clear();
for (int i=1;i<n;i++)
{
int s,e;
scanf("%d%d",&s,&e);
G[s].push_back(e);
G[e].push_back(s);
}
memset(son,0,sizeof(son));
ans=0;balance=INF;
dfs(1,0);
cout<<ans<<' '<<balance<<endl;
}
return 0;
}
NOIP 2018 旅行
題目
題解
1.如果的話,這就是一棵普通的樹,我們只要貪心選點(編號較小的優先遍歷)進行dfs即可。
2.如果的話,就是樹多連了一條邊,即基環樹,那麼求一個基環樹的字典序最小的遍歷序列該怎麼辦,經過老師的講解,以及看了半天題解後,我們可以想到我們會求樹的遍歷序列,而基環樹就是樹多加一條邊,那麼我們就可以列舉刪邊,然後依照第一種情況來寫,複雜度是O(n2)。
最後要說明的是:這份程式碼會T最後三個點。未來改進。
程式碼
#include<bits/stdc++.h>
using namespace std;
const int maxn=5050;
template<typename T>inline void read(T &x)
{
x=0;
T f=1,ch=getchar();
while (!isdigit(ch) && ch^'-') ch=getchar();
if (ch=='-') f=-1, ch=getchar();
while (isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48), ch=getchar();
x*=f;
}
vector<int>G[maxn];
int ans[maxn],edge[maxn][2];
int n,m;
namespace solve1
{
int cnt=0;
bool vis[maxn];
void dfs(int x,int fa)
{
ans[++cnt]=x;
vis[x]=1;
for (int i=0;i<G[x].size();++i)
{
int y=G[x][i];
if (!vis[y])
dfs(y,x);
}
}
void main()
{
memset(vis,0,sizeof(vis));
memset(ans,0,sizeof(ans));
cnt=0;//注意初始化
for (int i=1;i<=n;++i)
sort(G[i].begin(),G[i].end());//貪心選點,先遍歷編號小的點
dfs(1,0);
for (int i=1;i<=n;++i)
printf("%d ",ans[i]);
}
}
namespace solve2
{
int cnt=0,res[maxn];
bool vis[maxn];
bool cmp()
{
for (int i=1;i<=n;++i)
if (ans[i]!=res[i])
return ans[i]>res[i];//得到的答案不是未連通圖的情況
return false;
}
int deletex,deletey;
bool check(int x,int y)//避免這條邊已經被刪掉,然而又去遍歷的情況
{
if ((x==deletex&&y==deletey) || (x==deletey&&y==deletex))
return false;
return true;
}
void dfs(int x,int fa)
{
vis[x]=1;
res[++cnt]=x;
for (int i=0;i<G[x].size();++i)
{
int y=G[x][i];
if (!vis[y] && check(x,y))
dfs(y,x);
}
}
void main()
{
memset(ans,0x3f,sizeof(ans));
memset(vis,0,sizeof(vis));
for (int i=1;i<=n;++i)
sort(G[i].begin(),G[i].end());//同上
for (int i=1;i<=m;++i)
{
cnt=0;
memset(res,0,sizeof(res));
memset(vis,0,sizeof(vis));//初始化
deletex=edge[i][0];
deletey=edge[i][1];//列舉刪邊
dfs(1,0);
if (cmp()&&cnt==n)//已經統計出了答案且答案不是未連通圖的情況
memcpy(ans,res,sizeof(res));
}
for (int i=1;i<=n;++i)
printf("%d ",ans[i]);
}
}
int main()
{
read(n);read(m);
for (int i=1;i<=m;++i)
{
int x,y;
read(x);read(y);
G[x].push_back(y);
G[y].push_back(x);
edge[i][0]=x;//將要假刪除的一條邊
edge[i][1]=y;
}
if (m==n-1)
solve1::main();//如果是一棵樹的話
else
solve2::main();//如果是基環樹的話
return 0;
}
D. BZOJ 1791: [IOI2008]Island 島嶼 基環樹直徑
題目
程式碼
/**************************************************************
Problem: 1791
User: sjh
Language: C++
Result: Accepted
Time:8908 ms
Memory:95044 kb
****************************************************************/
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e6+10;
template<typename T>inline void read(T &x)
{
x=0;
T f=1,ch=getchar();
while (!isdigit(ch)) ch=getchar();
if (ch=='-') f=-1, ch=getchar();
while (isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48), ch=getchar();
x*=f;
}
int n,m,t;//t是識別符號
int ver[maxn<<1],edge[maxn<<1],next[maxn<<1],head[maxn],tot,du[maxn];
void add(int x,int y,int z)
{
ver[++tot]=y,edge[tot]=z,next[tot]=head[x],head[x]=tot,++du[y];
}
int c[maxn];//環上的點
int v[maxn];
int q[maxn<<1];
void bfs(int s,int t)
{
int l,r;
q[l=r=1]=s;//手寫佇列維護
c[s]=t;//標記連通塊(看每個節點屬於哪個基環樹)
while (l<=r)
{
for (int i=head[q[l]]; i; i=next[i])
if (!c[ver[i]])
{
q[++r]=ver[i];
c[ver[i]]=t;
}
l++;
}
}
ll f[maxn];//每顆子樹的直徑
ll d[maxn];//每個節點的子樹大小
void topsort()//找環操作順便處理一種情況(直徑不經過環)
{
int l=1,r=0,x,y;
for (int i=1; i<=n; ++i)
if (du[i]==1)//無向圖度數為1
q[++r]=i;
while (l<=r)
{
for (int i=head[x=q[l]]; i; i=next[i])
if (du[y=ver[i]]>1)//度大於1可更新答案
{
d[c[x]]=max(d[c[x]],f[x]+f[y]+edge[i]);//子樹內最長鏈
f[y]=max(f[y],f[x]+edge[i]);//f[x]表示x子樹中離x最遠的點的距離
if ((--du[y])==1)
q[++r]=y;
}
l++;
}
}
ll a[maxn<<1];
ll b[maxn<<1];
void dp(int t,int x)
{
int m=0,i,l=0,r,y=x;
do
{
a[++m]=f[y];
du[y]=1;
for (i=head[y]; i; i=next[i])
if (du[ver[i]]>1)//點在環上
{
y=ver[i];
b[m+1]=b[m]+edge[i];
break;
}
} while (i);//此時答案為 f[i]+f[j]+dis[i][j]的最大值,dis[i][j]表示環上i到j的最遠距離
if (m==2)//跑到環外,需要特判
{
for (i=head[y]; i; i=next[i])
if (ver[i]==x)
l=max(l,edge[i]);
d[t]=max(d[t],f[x]+f[y]+l);
return;
}
for (i=head[y]; i; i=next[i])//連線環的首尾
if (ver[i]==x)
{
b[m+1]=b[m]+edge[i];
break;
}
for (i=1; i<m; ++i)//由於是環,所以複製一份
{
a[m+i]=a[i];
b[m+i]=b[m+1]+b[i];
}
q[l=r=1]=1;
for (i=2; i<2*m; ++i)
{
while (l<=r && i-q[l]>=m) ++l;
d[t]=max(d[t],a[i]+a[q[l]]+b[i]-b[q[l]]);
while (l<=r && a[q[r]]+b[i]-b[q[r]]<=a[i]) --r;//單調佇列維護
q[++r]=i;
}
}
int main()
{
read(n);
for(int i=1; i<=n; ++i)
{
int x,y;
read(x);read(y);
add(i,x,y),add(x,i,y);
}
for (int i=1; i<=n; ++i)
if (!c[i])
bfs(i,++t);//統計有多少基環樹
topsort();//拓撲找環
memset(v,0,sizeof(v));//重新利用v陣列,當作基環樹是否算過
ll ans=0ll;
for (int i=1; i<=n; ++i)
if (du[i]>1 && !v[c[i]])//每個基環樹只跑一遍並且此時i是環上一點
{
v[c[i]]=1;
dp(c[i],i);//求基環樹的直徑
ans+=d[c[i]];
}
printf("%lld\n",ans);
return 0;
}
E. CF 835F Roads in the Kingdom 基環樹-刪邊
題目
解釋
這道題我是真的不會,看了兩堂課,最後只能以抄程式碼了結。。。附上大佬的連結:Rayment_cc
程式碼
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=2e5+10;
const ll inf=1e18;
template<typename T>inline int getmin(T &x,T y)
{
return x>y?x=y,1:0;
}
template<typename T>inline int getmax(T &x,T y)
{
return x<y?x=y,1:0;
}
template<typename T>inline void read(T &x)
{
x=0;
T f=1,ch=getchar();
while (!isdigit(ch) && ch^'-') ch=getchar();
if (ch=='-') f=-1, ch=getchar();
while (isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48), ch=getchar();
x*=f;
}
int ver[maxn<<1],edge[maxn<<1],Next[maxn<<1],head[maxn],len=-1;
inline void add(int x,int y,int z)
{
ver[++len]=y,edge[len]=z,Next[len]=head[x],head[x]=len;
}
int cnt;
inline int pre(int x)
{
return x==1?cnt:x-1;
}
inline int nxt(int x)
{
return x==cnt?1:x+1;
}
bool vis[maxn];
int cir[maxn];
ll sum[maxn];
inline int dfs(int x,int fa)
{
if (vis[x]) return x;
int tmp;
vis[x]=1;
for (int i=head[x];~i;i=Next[i])
if (i^fa)
if (tmp=dfs(ver[i],i^1))
{
if (tmp==-1) return -1;
cir[++cnt]=x;
sum[cnt]=edge[i];
return tmp==x?-1:tmp;
}
return 0;
}
ll dist[maxn],mxdist;
int id;
inline void bfs(int s,int ban1,int ban2)
{
queue<pair<int,int> >q;
mxdist=dist[s]=0ll;
id=0;
q.push(make_pair(s,-1));
while (!q.empty())
{
int x=q.front().first,u=q.front().second;
q.pop();
if (getmax(mxdist,dist[x])) id=x;
for (int i=head[x];~i;i=Next[i])
{
int y=ver[i],z=edge[i];
if (i^u && y^ban1 && y^ban2)
{
dist[y]=dist[x]+z;
q.push(make_pair(y,i^1));
}
}
}
}
ll dep[maxn],mx,ans,tmp;
ll p1[maxn],p2[maxn];
ll s1[maxn],s2[maxn];
ll m1[maxn],m2[maxn];
int main()
{
int n;
read(n);
memset(head,0xff,sizeof(head));
for (register int i=1;i<=n;++i)
{
int x,y,z;
read(x);read(y);read(z);
add(x,y,z);add(y,x,z);
}
dfs(1,-1);
for (register int i=1;i<=cnt;++i)
{
sum[i]+=sum[i-1];
bfs(cir[i],cir[pre(i)],cir[nxt(i)]);
dep[i]=mxdist;
bfs(id,cir[pre(i)],cir[nxt(i)]);
getmax(mx,mxdist);
}
ans=inf;
p1[0]=p2[0]=s1[cnt+1]=s2[cnt+1]=s2[cnt+2]=-inf;
for (register int i=1;i<=cnt;++i)
{
m1[i]=max(m1[i-1],dep[i]+sum[i]+p1[i-1]);
p1[i]=max(p1[i-1],dep[i]-sum[i]);
p2[i]=max(p2[i-1],dep[i]+sum[i]);
}
for (register int i=cnt;i;--i)
{
m2[i]=max(m2[i+1],dep[i+1]-sum[i+1]+s2[i+2]);
s1[i]=max(s1[i+1],dep[i]-sum[i]);
s2[i]=max(s2[i+1],dep[i]+sum[i]);
}
for (register int i=1;i<cnt;++i)
{
tmp=0ll;
getmax(tmp,m1[i]);
getmax(tmp,m2[i]);
getmax(tmp,sum[cnt]+s1[i+1]+p2[i]);
getmin(ans,tmp);
}
tmp=0ll;
for (register int i=2;i<=cnt;++i)
getmax(tmp,dep[i]+sum[i]+p1[i-1]);
getmin(ans,tmp);
getmax(ans,mx);
printf("%lld\n",ans);
return 0;
}
F. BZOJ 1040: [ZJOI2008]騎士 基環樹DP
題目
程式碼
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e6+5e2;
template<typename T>inline void read(T &x)
{
x=0;
T f=1,ch=getchar();
while (!isdigit(ch) && ch^'-') ch=getchar();
if (ch=='-') f=-1, ch=getchar();
while (isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48), ch=getchar();
x*=f;
}
int ver[maxn<<1],Next[maxn<<1],head[maxn],len;
inline void add(int x,int y)
{
ver[++len]=y,Next[len]=head[x],head[x]=len;
}
int n,power[maxn],hate[maxn],vis[maxn],U,V;
ll f[maxn],g[maxn];
inline void dfs(int x,int fa)//dfs找環
{
vis[x]=1;
for (int i=head[x];i;i=Next[i])
{
int y=ver[i];
if (y!=fa)
{
if (!vis[y]) dfs(y,x);
else
{
vis[y]=1;
U=x,V=y;
return ;
}
}
}
}
inline void tree_dp(int x,int fa,int rt,int ban)//ban 不選的點
{
vis[x]=1;
f[x]=power[x];
g[x]=0;
for (int i=head[x];i;i=Next[i])
{
int y=ver[i];
if (x==rt && i==ban) continue;
if (y!=fa && y!=rt)
{
tree_dp(y,x,rt,ban);
f[x]+=g[y];
g[x]+=max(g[y],f[y]);
}
}
}
int main()
{
read(n);
for (int i=1;i<=n;++i)
{
read(power[i]);read(hate[i]);
add(i,hate[i]),add(hate[i],i);
}
ll ans=0;
for (int i=1;i<=n;++i)
if (!vis[i])
{
dfs(i,-1);
int banu,banv;
for (int i=head[U];i;i=Next[i])
if (ver[i]==V)
{
banu=i;
break;
}
for (int i=head[V];i;i=Next[i])
if (ver[i]==U)
{
banv=i;
break;
}
tree_dp(U,-1,U,banu);//斷環為鏈並將斷開的兩個點強制其中一個點為根且不選,做一次樹形DP
ll uans=g[U];
tree_dp(V,-1,V,banv);//對另一個點做同樣操作
ll vans=g[V];
ans+=max(uans,vans);//取兩次結果最大值加入ans
}
printf("%lld\n",ans);
return 0;
}
小結
今天的題目真是和江蘇數學卷一樣,前半部分送分,後半部分送命。各個省選難度以上,所以,後三道題寫了程式碼的,其實都是抄題解的,不過也稍微理解了點,集訓結束後,還要回來把這些題再好好寫寫。。。。話說從明天開始,基本上題題都是省選級別以上,什麼Tanjan之類的,雖然之前看過,也寫了一點,然而還是很懵,我後面該怎麼過啊!
相關文章
- 樹的直徑
- 樹的重心
- 【圖論】樹的重心圖論
- 求樹的直徑(BFS/DFS)
- 樹的DFS序列,時間戳,樹的深度,重心時間戳
- 演算法筆記 - 樹的直徑演算法筆記
- D48 樹的直徑 P3304 [SDOI2013] 直徑
- 基環樹
- 【Codeforces1404B】Tree tag | 樹上追擊、博弈、樹的直徑
- 小A與尤拉路(牛客-樹的直徑)
- 【模板題】 543. 二叉樹的直徑二叉樹
- 基環樹和笛卡爾樹
- LeetCode第 543 題:二叉樹的直徑(C++)LeetCode二叉樹C++
- leetcode 每日一題 543 二叉樹的直徑 dfs方法LeetCode每日一題二叉樹
- CF 1805 D. A Wide, Wide Graph (*1800) 思維 + 樹的直徑IDE
- D49 樹的直徑 P2491 [SDOI2011] 消防
- 二叉樹、B樹以及B+樹二叉樹
- D52 樹的直徑+貪心 CF911F Tree DestructionStruct
- D50 樹的直徑 P3629 [APIO2010] 巡邏API
- 【演算法學習】基環樹演算法
- 樹7 堆中的路徑
- 基環樹的一些基本問題
- 二叉樹任意兩個節點間的最大距離(Java,LeetCode 543二叉樹的直徑 遞迴)二叉樹JavaLeetCode遞迴
- 路徑上若干條樹的包含
- 【題解】Solution Set - NOIP2024集訓Day10 樹的直徑、重⼼、中⼼
- 紅黑樹的原理以及實現
- 二叉樹的子結構、深度以及重建二叉樹二叉樹
- 關於樹上路徑異或和的思考
- 如何直觀形象地樹狀列印一棵二叉樹?二叉樹
- 二叉樹路徑查詢二叉樹
- 二叉樹路徑總和二叉樹
- 387,二叉樹中的最大路徑和二叉樹
- 資料結構基礎--字首樹&&字尾樹資料結構
- Android技能樹 — 樹基礎知識小結(一)Android
- [1483. 樹節點的第 K 個祖先] 【路徑】
- 124. 二叉樹中的最大路徑和二叉樹
- JavaScript 二叉搜尋樹以及實現翻轉二叉樹JavaScript二叉樹
- 樹套樹