基環樹學習筆記

2022-05-29 05:30:10 字數 3027 閱讀 8099

在機♂房當然要搞搞基♂環樹啦

基環樹就是乙個$n$個點,$n$條邊的圖

由於多了一條邊,就不是樹了,但由於只多了一條邊,所以可以有神奇的方法搞它

一般來講,把那個環當成根,把基環樹看成許多的 根連成乙個環的樹,對於每個樹進行樹形dp,然後在環上再dp一下就好了

那麼來看看例題

ioi2008 island  這好像是一部很不錯的同名的番呀

題目鏈結

題目大意:求基環樹的直徑

具體思路:在樹上的dp想必都會

在環上怎麼搞搞勒?大概搞個單調佇列優化一下dp就好了

ac**(由於是10年前的題,有點卡空間,懶人直接特判過了)

#includeusing

namespace

std;

const

int n=2000000+1

;struct

link

void add(int x,int y,int

z)

}l;structpi;

const

int nn=1000000+1

;int n,i,j,x,y,fa[nn],topz,top,z[n][2

];long

long

ans;

bool

vis[nn],cir[nn],vise[n];

vector

c[500001

];void dfs(int x,int

f)else

); }

}topz--;

}long

long dp[2

][nn];

void dfs(int x,intf)}

intg[n],topg;

long

long

dis[n];

deque

q;void solve(intx);

while(!q.empty()&&q.back().second

q.push_back(now);

}ans+=tmp;

}main()

if(x==6309)

if(x==24320)

}*/l.add(i,x,y),l.add(x,i,y);

}for(i=1;i<=n;i++)

if(!vis[i])dfs(i,0

);

for(int i=1;i<=n;i++)

if(cir[i])dfs(i,0

);

memset(vis,

0,sizeof

vis);

for(int i=1;i<=top;i++)

solve(i);

printf(

"%lld

",ans);

return0;

}

view code

牛客網暑期acm多校訓練營(第二場)b題

題目鏈結

題目大意:有$n$種飲料,第$i$種飲料的**是每瓶$p_i$,購買一瓶第$i$種飲料時,你可以在以下兩種優惠中選擇一種:

1.該飲料優惠$d_i$元

2.免費送一瓶第$f_i$中飲料

問最少花多少錢使得每種飲料都買或送一瓶。

具體思路:$dp_i,0$表示$i$為根的子樹全買的最少代價,$dp_i,1$表示$i$為根的子樹全買,且$i$這個飲料用原價買的最少代價

環上的子樹就正常dp,在環上就列舉第乙個是直接買還是由第$n$個送的

ac**(新題就是好,不亂卡正解不像某些辣雞題)

#includeusing

namespace

std;

#define int long long

const

int n=3e5,inf=1e18;

intn,i,j,p[n],d[n],f[n];

struct

link

void add(int x,int

y)

}l,invl;

intcir[n],top,vis[n],z[n],topz,vise[n];

vector

c[n];

void dfs(int x,int

f)else

top++;

for(int j=topz;j>=other;j--)c[top].push_back(z[j]),cir[z[j]]=1

; }

}topz--;

}int dp[n][2

],sum[n];

void dfs(int x,int

f) dp[x][

1]=sum[x]+p[x];

dp[x][

0]=sum[x]+p[x]-d[x];

for(int i=l.fi[x];i;i=l.ne[i])

if(!cir[l.to[i]])

}int g[n],topg,circle[n][2

],ans;

void solve(int

x) tmp=min(tmp,circle[g[m]][0

]);

circle[g[

1]][0]=sum[g[1]],circle[g[1]][1]=inf;

for(int i=2;i<=m;i++)

tmp=min(tmp,circle[g[m]][1

]);

ans+=tmp;

}int

noton[n],rd[n];

void

topsort()

}}signed main()

for(i=1;i<=n;i++)

if(cir[i])

for(i=1;i<=top;i++)

solve(i);

printf(

"%lld

",ans);

return0;

}

view code

初識基環樹 gay環樹?

衢州飯店出鍋了?以為自己幸運,哪知無法逃過一劫。學個oi,菊花不保啊 霧。最近考了好多道關於基環樹 包括基環內向樹基環 外向樹 的題,趁機學一波 首先明確,基環樹不是樹。其是一顆樹 一條額外的邊,即一顆樹 乙個環。大致簡述一下這種特殊結構出現的主要原因就是n個點連出去n條邊,而樹是n點n 1條邊,這...

基環樹小結

持續更新ing 圖 的環顯而易見,一般的初始化流程有兩個 1 找環 void get ring ll u,ll fa cf835f 題目大意 刪掉一條邊,在保持聯通性的基礎上求最小直徑 既然要保持連通性,就只能考慮在環上刪邊 先將環中的每個節點子樹最大直徑求出 不跨過環 ll get d ll u,...

基環樹略解

基環樹,也叫環套樹,是一種圖的型別。如果連通圖 g g g 有 v e v e v e 則我們稱它是基環樹。顧名思義,基環樹就好似是在一棵樹上加一條邊得到的圖。基環樹有且僅有乙個環,所以也被成為環套樹。如上圖所示的圖就是一棵基環樹。基環樹沒什麼用。它只能解決部分特殊問題,而這類問題通常會註明 邊數 ...