問題を解決P2458 [[SDOI2006]セキュリティガード]

トピックリンク

ソリューション[SDOI2006]警備員

タイトル効果:指定された\(n-は\)木の点は、各点が全ての点をカバーするために必要最小限の設定点、それに接続されたすべてのポイントをカバーすることができます。

我々は、([D [U] fを\ ] \) で表される\(U \) ツリーのサブツリーのルートである\(U \)状態点をカバーである(D \)\で過ごした極小点を(\ (D = 0 \)場合\(U \)点は、親ノード、によって覆われている\(D = 1 \)の場合\(U \)ポイントは、独自で覆われている\(D = 2 \)場合\(U \)ポイントキルトノードカバレッジ)

それから

\ [分[U] [0] = \ sum_ {息子におけるV \(U)} F(F [v] [1]、F [v] [2])\]

\(分[U] [1] = \ sum_ {息子におけるV \(U)} F(F [v] [0]、F [v] [1]、[V] [2])+ヴァル(Fバツ)\)

\(fは[U]は[2] F F [X] [1] + \ sum_ {息子におけるV \(U)、V \ NEQ X}分(= [V] [1]、[V] [2 F ])\)

キーは、\([U] [2 F ] \) プロセスの\(N-2 ^ \)列挙時間爆発

我々は、前処理されてもよい\((合計= \和分 F [v] [1]、F [v] [2])\)

次に\(F [U] [2 ] =分\ {和-分(F [v] [1]、F [v] [2])+ F [v] [1] \} \)

コード:

#include <cstdio>
#include <vector>
using namespace std;
const int maxn = 2048;
vector<int> G[maxn];
template <typename T>
inline T min(const T &a,const T &b,const T &c){
    return min(a,min(b,c));
}
inline void addedge(int from,int to){
    G[from].push_back(to);
}
int f[maxn][3],val[maxn];
void dfs(int u,int faz){
    int sum = 0;
    f[u][1] = val[u];
    f[u][2] = 0x7fffffff;
    for(int v : G[u])
        if(v != faz){
            dfs(v,u);
            f[u][0] += min(f[v][1],f[v][2]);    
            f[u][1] += min(f[v][0],f[v][1],f[v][2]);
            sum += min(f[v][1],f[v][2]);
        }
    for(int v : G[u]){
        if(v == faz)continue;
        f[u][2] = min(f[u][2],sum - min(f[v][1],f[v][2]) + f[v][1]);
    }
}
int n,u,m,v;
int main(){
    scanf("%d",&n);
    for(int i = 1;i <= n;i++){
        scanf("%d",&u),scanf("%d %d",val + u,&m);
        while(m--)scanf("%d",&v),addedge(u,v),addedge(v,u);
    }
    return dfs(1,0),printf("%d\n",min(f[1][1],f[1][2])),0;
}

おすすめ

転載: www.cnblogs.com/colazcy/p/11515083.html