BZOJ4006 JLOI2015 管道連線

2022-05-03 16:36:11 字數 1374 閱讀 9409

傳送門題目要求相同顏色的點必須在乙個連通塊中,但會有多個顏色同屬乙個連通塊使得解更優的情況。

想一想dp能否行得通:設\(g_i\)表示已考慮顏色狀態為\(i\)時,最小合法方案的代價。

首先,\(g_i\)可以有乙個直觀的初值:由顏色屬於\(i\)的點構建的一棵最小生成樹的邊權和。(初始化)

​  接下來,如何考慮兩部分顏色各自的連通塊合起來作為最優解的情況?(兩子集合並更新)

​  更新\(g_i\)時,我們列舉\(i\)的兩個不相交子集\(s_1,s_2\)且\(s_1|s_2=i\),並用\(g_+g_\)來更新\(g_i\),即直接嘗試將兩個連通塊取交。不需要擔心兩部分會有重複計算某一條邊的情況,因為這是子集列舉dp,有邊重複計算的轉移自然不會成為最優轉移,最優的轉移一定會被列舉到(或者就是初值最優)。

​  以上兩種方法並用,就可以順利dp出\(g\)。

​  答案就是\(g_\)。\(all\)是包含所有顏色的集合。

​  對於\(g\)的初值,直接用斯坦納樹計算所有關鍵點的不同組合的最小生成樹即可。

#include #include #include using namespace std;

const int n=1005,m=3005,c=10,inf=1e9;

int n,m,p,col[n],tin[n][2],colst[c+1];

int idcnt,id[n],rep[c+1];

int clis[c+1],ccnt;

int f[n][1bool inq[n];

int h[n],tot;

struct edgee[m*2];

inline int bit(int i)

inline bool in(int st,int i)

inline void addedge(int u,int v,int w); h[u]=tot;

e[++tot]=(edge); h[v]=tot;

}void read()

for(int i=1,c,u;i<=p;i++)

sort(clis+1,clis+1+ccnt);

ccnt=unique(clis+1,clis+1+ccnt)-clis-1;

for(int i=1,u,c;i<=p;i++)

}void spfa(int st)

}} }

}void steinertree()

for(int j=1;jif(f[i][j]!=inf)

q.push(i),inq[i]=true;

} spfa(j); }}

void solve()

printf("%d\n",g[all-1]);

}int main()

bzoj4006 JLOI2015 管道連線

傳送門 思路 一眼看上去很像斯坦納樹 但是限制稍有不同,只要每種顏色的點聯通即可 也就是說最後可能是森林 我聽說裸寫斯坦納樹有90 所以我們要在外面再套一層dp f i j 還是斯坦納樹的狀態,i是以i為根,j是狀態為j 先用斯坦納樹求出每種聯通狀況的最小費用 再設dp i 表示i這個狀態的最小費用...

bzoj4006 JLOI2015 管道連線

小銘銘最近進入了某情報部門,該部門正在被如何建立安全的通道連線困擾。該部門有 n 個情報站,用 1 到 n 的整數編號。給出 m 對情報站 ui vi 和費用 wi,表示情 報站 ui 和 vi 之間可以花費 wi 單位資源建立通道。如果乙個情報站經過若干個建立好的通道可以到達另外乙個情報站,那麼這...

bzoj 4006 JLOI2015 管道連線

time limit 30 sec memory limit 128 mb submit 1062 solved 576 submit status discuss 小銘銘最近進入了某情報部門,該部門正在被如何建立安全的通道連線困擾。該部門有 n 個情報站,用 1 到 n 的整數編號。給出 m 對情...