LOJ- palace guard

 

topic

Topic Link

 

Test score: 100

 

 

Main Algorithm: Minimum coverage tree DP, the point, a bipartite graph (Hungarian Algorithm)

 

 

Casual working:

   Weighted Minimum coverage

 

 

Test-taking strategies:

  The title says very clearly, covering all points with the least points. Title given is a tree, so you can use dynamic programming to solve.
  Given the following definition:
  F. [I, 0] indicates hold point i, i can be observed parent node;
  F. [I,. 1] represents a hold point i, i son nodes may be observed;
  F. [I, 2 ] i represents the point of discharge, is provided at the guards i;
  transfer follows:
    . 1, [i, 0] is defined by the apparent F., son node i and j, the son node needs to be observed, but the root hold i , it must ensure that the son can be observed, i.e., F [j] [1], F [j] [2], so we need to enumerate the son node must be placed, namely the:
      F. [I, 0] = [Sigma ( min (F [j] [1 ], F [j, 2]))}
        where i is the son node enumeration

    2, [i, 1] is defined by the apparent F., The son i of the node must have a direct security node, the other node must be the son observed, i.e. the:
      F. [I,. 1] = min ([Sigma (min (F [j, 1 ], F [j, 2]) + F [k, 2])
        where k is the son of the node will put enumeration, j k son nodes other than the
    3 by F [i, 2] define understood, I placed point guard, it can be observed that for each son node, taking F [j, 0], F [j, 1], F [j, 2] that is the minimum value can, i.e. the:
      F. [i, 2] = min (F. [J, 0], F. [J,. 1], F. [J, 2])
        J is the son node i

  Code

/*题目说的很清楚,用最少的点覆盖所有的点。题目给出的是个树,所以可以用动态规划来解决。
    给出如下定义:
        F[i,0]表示i点不放,i可以被父亲节点观察到;
        F[i,1]表示i点不放,i可以被儿子节点观察到;
        F[i,2]表示i点放,在i处设置警卫;
    转移如下:
    1、由F[i,0]定义可知,设j为i的儿子节点,儿子节点都需要被观察到,但由于根节点i不放,所以儿子必须保证能被观察到,即F[j][1],F[j][2],所以我们需要枚举必须放置的儿子节点,即下:
          F[i,0] = ∑(min(F[j][1],F[j,2]))}
            其中i为枚举儿子节点

    2、由F[i,1]定义可知,i的儿子结点中一定有一个结点有直接警卫,其它儿子节点必须都要被观察到,即下:
          F[i,1] =min(∑(min(F[j,1],F[j,2])+F[k,2])  
            其中k为枚举的必放的儿子节点,j为除了k之外的儿子节点
    3、由F[i,2]定义可知,i点放置了守卫,所以对于每个儿子节点都能被观察到,取F[j,0],F[j,1],F[j,2]最小值即可,即下:
          F[i,2] = min(F[j,0],F[j,1],F[j,2]) 
              j是i的儿子节点*/

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define FORa(i,s,e) for(int i=s;i<=e;i++)
#define FORs(i,s,e) for(int i=s;i>=e;i--)

using namespace std;
const int N=1500,M=1500,INF=2147483647;
int n,m,root,num_edge,head[N+1],a[N+1],f[N+1][3];
/*f[u][0]表示的是结点u可以被父亲看到的安排的u为树根的子树安排的最少的警卫数
 f[u][1]表示的是结点u可以被儿子看到的安排的u为树根的子树安排的最少的警卫数
 f[u][2]表示的是结点u上安排警卫时的u为树根的子树安排的最少的警卫数
*/
struct Edge{
    int next,to;
}edge[2*M+2]; 
void Add_edge(int from,int to) {edge[++num_edge]=(Edge){head[from],to},head[from]=num_edge;}
inline int min(int fa,int fb){return fa<fb?fa:fb;}
void Dp(int u,int fa)
{
    int d=INF;
    for(int i=head[u];i;i=edge[i].next)
    {
        int v=edge[i].to;
        if(v!=fa)
        {
            Dp(v,u);
            f[u][0]+=min(f[v][1],f[v][2]);
            f[u][1]+=min(f[v][1],f[v][2]);
            d=min(d,f[v][2]-min(f[v][1],f[v][2]));
            f[u][2]+=min(f[v][0],min(f[v][1],f[v][2]));
        }
    }
    f[u][1]+=d,f[u][2]+=a[u];
    /*状态转移方程
        当点u可以被父亲看到的安排的u为树根的子树安排的最少的警卫数为保证子结点能够全部观察到,则为min(f[v][1],f[v][2])的和
         当点u可以被儿子看到的安排的u为树根的子树安排的最少的警卫数为保证子结点能够全部观察到,则至少有一个儿子结点必须要选,F[i,0] = min{∑(min(F[j][0],F[j,2]))+F[k,2]}
        当点u上安排警卫时的u为树根的子树安排的最少的警卫数为儿子结点的三者的min,F[i,2] = min(F[j,0],F[j,1],F[j,2]) 
    */ 
}
int main()
{
    int from,to,fcnt;
    scanf("%d",&n);
    FORa(i,1,n)
    {
        scanf("%d",&from),scanf("%d%d",&a[from],&fcnt);
        FORa(j,1,fcnt) scanf("%d",&to),Add_edge(from,to),Add_edge(to,from);
    }
    root=1,Dp(root,0);
    printf("%d",min(f[root][1],f[root][2]));
    return 0;
}
/*6
1 30 3 2 3 4
2 16 2 5 6
3 5 0
4 4 0
5 11 0
6 5 0*/

 

总结:

  1.确定建立模型

  2.构建知识架构,模型体系

 

 

 

题目说的很清楚,用最少的点覆盖所有的点。题目给出的是个树,所以可以用动态规划来解决。
     给出如下定义:
F[i,0]表示i点不放,且以i为根节点的子树(包括i节点)全部被观察到;
F[i,1]表示i点不放,且以i为根节点的子树(可以不包括i节点)全部被观察到;
F[i,2]表示i点放,且以i为根节点的子树全部被观察到;
     转移如下:
1、由F[i,0]定义可知,设j为i的儿子节点,至少要有一个i的儿子节点是放置守卫的,其余的儿子节点可放可不放,但由于根节点i不放,所以其余的儿子节点如果不放的话,必须保证能被观察到,即F[j][0];所以我们需要枚举必须放置的儿子节点,即下:

  F[i,0] = min{∑(min(F[j][0],F[j,2]))+F[k,2]}

其中k为枚举的必放的儿子节点,j为除了k之外的儿子节点


2、由F[i,1]定义可知,i可以被观察到也可以不被观察到,但儿子节点必须都要被观察到,即下:

  F[i,1] =∑(min(F[j,0],F[j,2])) 

  j是i的儿子节点


3、由F[i,2]定义可知,i点放置了守卫,所以对于每个儿子节点都能被观察到,取F[j,0],F[j,1],F[j,2]最小值即可,即下:
  F[i,2] = min(F[j,0],F[j,1],F[j,2]) j是i的儿子节点

对于叶节点i,F[i,0] = F[i,2] = data[i],F[i,1] = 0;

讲得已经十分详细了,剩下自己解决吧。

Guess you like

Origin www.cnblogs.com/SeanOcean/p/11314323.html