ZJOI2008 騎士 題解

2022-07-13 21:06:20 字數 1849 閱讀 4301

題面

這道題稍微想一想就會聯想到樹形dp的入門題:沒有上司的舞會;

但是再想一想會發現這根本就不是一顆樹,因為它比樹多了一條邊;

這時候我們引入乙個新的概念:基環樹;

顧名思義(??),基環樹就是在一顆樹上填一條邊構成的乙個圖;基環樹也叫環套樹(明明更像樹套環)。

我們在樹上可以做的事情基本都可以在基環樹上實現:比如樹形dp

基環樹的基本解題思路就是找到在環上的兩個點:s,t;

分別以s,t為根來跑一邊dp,這樣把兩次的答案進行處理就可以解決掉這道題;

那麼怎樣找環?我總結了幾種不同的思路:

1.並查集找環:對於要加入的兩個點如果已經在同乙個區域內,那麼他們一定在環上;

2.tarjan找環:對於乙個點,如果dfn[v]

3.dfs找環:其實和tarjan的基本思路一樣,如果乙個點的子節點v已經被經過,那麼u和v就在乙個環上;

#include #define int long long

using namespace std;

struct littlestarstar[2000010];

int head[2000010],cnt;

void add(int u,int v)

int ha[1000010],fa[1000010];

int f[1000010],g[1000010],vis[1000010];

void dfs(int u,int goal)

dfs(v,goal);

g[u]+=max(g[v],f[v]);

f[u]+=g[v];

}}int ans;

signed main()

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

dfs(root,root);

int tmp=max(g[root],f[root]);

vis[root]=1;

memset(f,0,sizeof(f));

memset(g,0,sizeof(g));

root=fa[root];

dfs(root,root);

tmp=max(tmp,max(g[root],f[root]));

memset(f,0,sizeof(f));

memset(g,0,sizeof(g));

ans+=tmp;}}

cout《然後可以雙倍經驗:洛谷 p1453 城市環路

#include using namespace std;

struct littlestarstar[200010];

int head[200010],cnt;

void add(int u,int v)

int ha[100010],fa[100010];

double f[100010],g[100010];

void dfs(int u,int ff)

dfs(v,u);

f[u]+=g[v];

g[u]+=max(g[v],f[v]);

}}inline int zhaobaba(int x)

int s,t;

int main()

add(u,v);

add(v,u);

fa[zhaobaba(v)]=zhaobaba(u);

}double ans=0,k;

scanf("%lf",&k);

dfs(s,0);

ans=g[s];

dfs(t,0);

ans=max(ans,g[t]);

printf("%.1lf",ans*k);

}

ZJOI2008 騎士 基環樹

題意見鏈結。本題較為經典,值得一做。基環外向樹練手好題。如果不考慮環的情況,則就是普通樹形dp,f i 0 1 表示這個點取或不取。對於此題一棵樹只能出現乙個環,我們任意刪去環上的一條邊,即可轉環為樹。對於 u,v 1 u 不取,則以 u 為根dp。2 v 不取,則以 v 為根dp。不需要考慮兩個點...

ZJOI2008 騎士(基環樹 DP)

看似有向邊,其實可以轉化為無向邊。構成乙個基環森林 但是需要特判一種情況 當有兩個人互相討厭的時候,形成一棵樹,同時有重邊 我的找環做法需要sort判重,可能有更好的方法 然後把森林裡的每一棵樹或者基環樹dp一下 就是沒有上司的舞會模型,超水 把答案加起來 注意會爆int 做完了 include i...

ZJOI2008 泡泡堂題解

一道博弈論貪心題 如下 213 242 06 10000000 10000000 10000000 10000000 10000000 1000000000 000012 12我們分別稱 4 位選手為 a,b,c,d 則可能出現以下 4 種對戰方式,最好情況下可得 2 分,最壞情況下得 0 分。浙江...