1.没有上司的舞会
一条边上最多选择一个点
#include
#include
#include
#include
using namespace std;
int num[6100];
int deg[6100];
int dp[6100][2];
int h[6100],ver[6100],ne[6100],cnt=0;
void add(int a,int b)
{
ver[cnt]=b;
ne[cnt]=h[a];
h[a]=cnt++;
}
void dfs(int u,int fa)
{
dp[u][1]=num[u];
dp[u][0]=0;
for(int i=h[u];i!=-1;i=ne[i])
{
int y=ver[i];
if(y==fa) continue;
dfs(y,u);
dp[u][1]+=dp[y][0];
dp[u][0]+=max(dp[y][1],dp[y][0]);
}
}
int main()
{
int n;
cin>>n;
memset(h,-1,sizeof h);
for(int i=1;i<=n;i++)
{
scanf("%d",&num[i]);
}
for(int i=0;i<n-1;i++)
{
int x,y;
scanf("%d%d",&x,&y);
add(y,x);
deg[x]++;
}
int ans=0;
for(int i=1;i<=n;i++)
{
if(!deg[i])
{
ans=i;
dfs(i,0);break;
}
}
printf("%d\n",max(dp[ans][1],dp[ans][0]));
}
2.战略游戏
一条边上最少选择一个点
#include
#include
#include
#include
using namespace std;
int n;
const int N=2000;
int h[N],e[N*2],ne[N*2],idx;
int deg[N];int dp[N][2];
void add(int a,int b)
{
e[idx]=b;
ne[idx]=h[a];
h[a]=idx++;
}
void dfs(int x)
{
dp[x][0]=0;dp[x][1]=1;
for(int i=h[x];i!=-1;i=ne[i])
{
int j=e[i];
dfs(j);
dp[x][0]+=dp[j][1];
dp[x][1]=min(dp[j][0]+dp[x][1],dp[j][1]+dp[x][1]);
}
}
int main()
{
while(scanf("%d",&n)!=EOF)
{
memset(h,-1,sizeof h);
memset(deg,0,sizeof deg);
memset(dp,0,sizeof dp);
idx=0;
for(int i=0;i<n;i++)
{
int x,num;
scanf("%d:(%d)",&x,&num);
x++;
for(int j=1;j<=num;j++)
{
int y;
scanf("%d",&y);y++;
deg[y]++;
add(x,y);
}
}
int root=0;
for(int i=1;i<=n;i++)
{
if(deg[i]==0)
{
root=i;
dfs(i); break;
}
}
cout<<min(dp[root][1],dp[root][0])<<endl;
}
}
皇宫各个宫殿的分布,呈一棵树的形状,宫殿可视为树中结点,两个宫殿之间如果存在道路直接相连,则该道路视为树中的一条边。
已知,在一个宫殿镇守的守卫不仅能够观察到本宫殿的状况,还能观察到与该宫殿直接存在道路相连的其他宫殿的状况。
大内保卫森严,三步一岗,五步一哨,每个宫殿都要有人全天候看守,在不同的宫殿安排看守所需的费用不同。
可是陆小凤手上的经费不足,无论如何也没法在每个宫殿都安置留守侍卫。
帮助陆小凤布置侍卫,在看守全部宫殿的前提下,使得花费的经费最少。
#include
#include
#include
#include
using namespace std;
const int N=2000;
int a[N],h[N],e[N*2],ne[N*2],idx;
int deg[N];
int dp[N][3];
void add(int a,int b)
{
e[idx]=b;
ne[idx]=h[a];
h[a]=idx++;
}
//dp[x][0]被父节点看到
//dp[x][1]被子节点看到
//dp[x][2]在x节点放
void dfs(int x)
{
dp[x][0]=0;
dp[x][2]=a[x];
int sum=0;
for(int i=h[x];i!=-1;i=ne[i])
{
int j=e[i];
dfs(j);
dp[x][0]+=min(dp[j][2],dp[j][1]);
dp[x][2]+=min(dp[j][1],min(dp[j][0],dp[j][2]));
sum+=min(dp[j][1],dp[j][2]);
}
dp[x][1]=1e9;
for(int i=h[x];i!=-1;i=ne[i])
{
int j=e[i];
dp[x][1]=min(dp[x][1],sum-min(dp[j][1],dp[j][2])+dp[j][2]);
}
}
int main()
{
int n;
cin>>n;
int num,x;
memset(h,-1,sizeof h);
for(int i=1;i<=n;i++)
{
int ans;
scanf("%d%d%d",&x,&ans,&num);
a[x]=ans;
for(int j=1;j<=num;j++)
{
int y;scanf("%d",&y);
deg[y]++;
add(x,y);
}
}
int root;
for(int i=1;i<=n;i++)
{
if(!deg[i])
{
root=i;
dfs(i);
break;
}
}
cout<<min(dp[root][2],dp[root][1])<<endl;
}