傳送門題目要求相同顏色的點必須在乙個連通塊中,但會有多個顏色同屬乙個連通塊使得解更優的情況。
想一想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 對情...