基環樹 18牛客多校2B discount

2021-08-21 17:04:30 字數 1690 閱讀 7790

sou

rce:

source:

source

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

p ro

blem

:problem:

proble

m:n種物品,兩種買法,一種選擇折扣價,一種選擇原價購買,使得自己的父親可以免費。求最小值買下全部物品。

i de

a:

idea:

idea

:基環內向樹dp。先找到樹上的環,對於環上的每個點懸掛的樹都跑一次樹dp。然後斷環為鏈,跑一次鏈dp。鏈上考慮兩種情況,斷開的邊為u->v,分別考慮u對v有貢獻和u對v無貢獻,之後v->v1->…->u dp得到對應的最小值,即circle[u][1]和circle[u][0]。

比賽的時候現學基環內向樹dp失敗

c od

e:

code:

code

:

#includeusing namespace std;

#define lc o<<1

#define rc o<<1|1

#define fi first

#define se second

#define pb push_back

#define all(x) (x).begin(), (x).end()

#define bcnt(x) __builtin_popcountll(x)

#define clr(a, x) memset(a, x, sizeof(a))

#pragma comment(linker, "/stack:1024000000,1024000000")

#define debug printf("passing [%s] in line %d\n",__function__,__line__)

using db = double;

using ll = long long;

using pii = pair;

const int n = 1e5+10;

const ll inf = 1e18;

bool cir[n];

int p[n], d[n], f[n], vis[n];

ll dp[n][2], c[n][2], sum[n];

vectorg[n], g;

void dfs(int u, int fa)

::sum[u] = sum;

dp[u][0] = min(sum+p[u]-d[u], sum+tmp);

dp[u][1] = sum+p[u];

}ll solve(int u)

g.clear();

while(vis[u] == 1)

for(int u:g) dfs(u, 0);

ll ret = inf;

for(int x = 0; x < 2; x++)

ret = min(ret, c[g.size()-1][x]);

}return ret;

}int main()

ll ans = 0;

for(int i = 1; i <= n; i++) if(!vis[i])

printf("%lld\n", ans);

return 0;

}

2018 牛客多校 2

problem a problem b 考慮第二種優惠,每乙個物品如果原價購買了,那麼向可以免費拿的那個物品連一條邊 在樹上被指向的那個點是父親 如果不考慮環的話,考慮樹上dp。設 f i 0 表示買掉以 i 為根的子樹需要的最小花費,設 f i 0 表示買掉以 i 為根的子樹並且 i 這個點是原價...

牛客多校1 1or2

題意 給定一張n點m邊的圖,以及每個點的理想出入度,求是否能夠通過選擇某些邊來使得新圖上每個點的出入度為理想出入度 做法 由於d i 的範圍為1 2,說明新圖中的連通分量要麼是鏈,要麼是環。對於此類最大匹配問題,可以用網路流來解決,但是由於可能存在奇環,這將導致找增廣路時,傳統的dinic演算法時間...

牛客多校2 Cover the tree

題意 給定一棵無根樹,求用最少的鏈覆蓋樹上所有的邊,並輸出每條鏈的首位兩端編號 做法 首先確認需要多少條鏈來覆蓋所有邊。顯然,當n 1時,只需要一條,鏈頭尾編號都為1 當n 2時,需要一條,鏈頭尾為1,2 當n 3時,上述兩種情況鏈的頭尾都是入度為1的點,而確實,當從乙個葉子節點1出發,向上走到假定...