給定一棵樹,點數為n,從根節點出發,每一步可以走向與當前點有直接邊相連的點,問走m步最多能經過多少個點。邊和點均可以重複經過,但不重複計數。\(f[p][j]\) 表示從 \(p\) 出發走向以 \(p\) 為根的子樹,一共走 \(k\) 步並且最終回到 \(p\),最多能經過的點數。
\(g[p][j]\) 表示從 \(p\) 出發走向以 \(p\) 為根的子樹,一共走 \(k\) 步並且最終不回到 \(p\),最多能經過的點數。
考慮 \(f[p][j]\) 的轉移,走的情況應該是從 \(p\) 出發,走向某棵子樹,再走回 \(p\),再走向某棵子樹,再走回 \(p\),……,最後走回 \(p\)。
列舉 \(p\) 的所有子樹,對於當前的子樹 \(x\),考慮分配給其多少步 \(k\),由於還要走回 \(p\),故 \(k\) 的範圍即是 \([0,j-2]\),狀態轉移方程即為:
\[f[p][j]=\mathop_\
\]邊界:\(f[p][0]=1\)。
考慮 \(g[p][j]\) 的轉移,對於當前的子樹 \(x\),走的情況無非以下兩種:
對於第一種情況:
\[g[p][j]=\mathop_\
\]對於第二種情況:
\[g[p][j]=\mathop_\
\]邊界:\(g[p][0]=1\)。
最後的答案為 \(g[0][1 \ldots m]\) 中的最大值,因為如果不足 \(m\) 步就達到了最大值的話,剩下的步數可以隨便走。
#include #include #include #include using namespace std;
const int n=110;
struct edgeedge[n<<1];int idx;
int h[n];
void add_edge(int u,int v);h[u]=idx;}
int f[n][n];
int g[n][n];
int n,m;
void dfs(int p,int fa) }}
int main()
dfs(1,0);
int ans=0;
for(int i=1;i<=m;i++)ans=max(ans,g[1][i]);
printf("%d\n",ans);
return 0;
}
CQOI2017 小Q的棋盤
問題描述 小q正在設計一種棋類遊戲。在小q設計的遊戲中,棋子可以放在棋盤上的格點中。某些格點之間有連線,棋子只能 在有連線的格點之間移動。整個棋盤上共有v個格點,編號為0,1,2 v 1,它們是連通的,也就是說棋子從任意格 點出發,總能到達所有的格點。小q在設計棋盤時,還保證棋子從乙個格點移動到另外...
CQOI2017 小Q的棋盤
看到這道題,很容易想到是一道樹型dp,那麼該如何做?首先我們可以先這樣定義狀態,fi,jf fi,j 表示以i ii為根節點,向下走j jj步最多能經過多少點,但很明顯,只是這樣是不行的,所以我們再加一維,第三維為0表示不會到根節點,第三維為1表示需要回到根節點,那麼就可以得出狀態轉移方程 f ma...
CQOI2017 老C的方塊
傳送門 nkoj4042 這是一道網路流題。我在這道題上耗了很久 感謝 oblack幫我修改 這道題的思維上的難度並不大。以下是我的想法 首先要確定乙個大的方向,題目中要求移除一些方塊使得剩餘方塊無法構成 討厭的形狀 很容易就想到了最小割。仔細觀察一下,可以發現這些討厭的形狀是由兩個方格 一條特殊的...