首页 > 其他分享 >HDU 1054 Strategic Game 树形DP/二分图匹配

HDU 1054 Strategic Game 树形DP/二分图匹配

时间:2023-09-15 10:36:17浏览次数:47  
标签:二分 HDU 1054 int num Strategic 树形 1505 dp


第一次写博文,想了半天就拿一道dp/graph的题作为处作吧

此题有两种常见解法

(题意比较简单,就不赘述)

1.二分图最大匹配

        此题等价于问一棵树中最小点覆盖数。树形结构可以把它看做是一个二分图,一个点集为奇数层,另一个点集为偶数层,显然满足二分图定义,可以套用求二分图最小点覆

盖的方法。或者,补全二分图,根据对称性,就是前面构造的二分图的边数的二倍,故最后结果也要除以二。

2.树形dp

        写树形dp时首先要考虑好每个点的可能状态,这个题中就是选不选这个点。然后就是写状态转移方程

        dp[i][0]=sum{dp[j][1]};

        dp[i][1]=sum{min(dp[i][0],dp[i][1])};

        (j为i的孩子节点集合)

        最后答案就是dp[i][0]和dp[i][1]的最小值(i为根节点)

#include<stdio.h>
#include<string.h>
int n,num,dps[1505][2],begin;
struct edge{
    int to;
    int next;
}edges[1505];
int head[1505];
void addedge(int u,int v){
    edges[num].to=v;
    edges[num].next=head[u];
    head[u]=num++;
}
int Min(int u,int v){
    return u<=v?u:v;
}
void dp(int u){
    int v,i;
    dps[u][0]=0;
    dps[u][1]=1;
    for(i=head[u];i!=-1;i=edges[i].next){
        v=edges[i].to;
        dp(v);
        dps[u][0]+=dps[v][1];
        dps[u][1]+=Min(dps[v][0],dps[v][1]);
    }
}
main(){
    int i,j,u,v,k;
    while(scanf("%d",&n)==1){
        num=1;
        memset(head,-1,sizeof(head));
        begin=-1;
        for(i=1;i<=n;i++){
            scanf("%d:(%d)",&u,&k);
            for(j=1;j<=k;j++){
                scanf("%d",&v);
                addedge(u,v);
            }
            if(k!=0 && begin==-1)
                begin=u;
        }
        dp(begin);
        printf("%d\n",dps[begin][1]<=dps[begin][0]?dps[begin][1]:dps[begin][0]);
    }
}

两种方法树形dp要快一些,毕竟一棵树边很少

标签:二分,HDU,1054,int,num,Strategic,树形,1505,dp
From: https://blog.51cto.com/u_16263395/7478009

相关文章

  • hdu 4712 Hamming Distance-----随机
    计算出二进制数中有多少个1:数据范围太大,想到可以随机如果你在第一次调用rand()之前没有调用srand(),那么系统会为你自动调用srand()。------百度rand#include<cstdio>#include<cstring>#include<algorithm>#include<time.h>usingnamespacestd;constintN=1e5+10......
  • hdu 4705 Y
    dfs1.要#pragmacomment(linker,"/STACK:16777216")2.扩栈要vc++编译环境3.不能用%lld,要用%I64d,无语。。#pragmacomment(linker,"/STACK:16777216")//手动扩栈#include<stdio.h>#include<string.h>#include<stdlib.h>#include<vector>using......
  • hdu-3926-Hand in Hand-并查集
    判断两个图是否同构。。用了并查集。。#include<stdio.h>#include<string.h>#include<stdlib.h>#include<algorithm>#include<queue>#include<stack>usingnamespacestd;#definelllonglongintn,m;structnode{ intfu; intsum; intf......
  • HDU 2955 Robberies
    01背包银行总钱数==容量V概率可以算安全的概率p=1-p;#include<stdio.h>#include<string.h>#include<algorithm>usingnamespacestd;doublepp,p[10001],f[10001];intv[10001];intmain(){ intt; scanf("%d",&t); while(t--){ intn,j,i,k,sum......
  • hdu 1372 Knight Moves 骑士的移动 bfs--马走日
    #include<stdio.h>#include<string.h>#include<queue>usingnamespacestd;charss[3],ee[3];intx1,y1,x2,y2;structpos{intx,y,step;}sta,end;intf[10][10];intdir[8][2]={1,2,1,-2,-1,2,-1,-2,2,1,2,-1,-2,1,-2,-1};boolfan......
  • 二叉树 遍历 hdu-1710-Binary Tree Traversals
    给出二叉树的前序遍历和中序遍历,求后序遍历。。 算法:由前序遍历的第一个元素可确定左、右子树的根节点,参照中序遍历又可进一步确定子树的左、右子树元素。如此递归地参照两个遍历序列,最终构造出二叉树。 由前序和中序结果求后序遍历结果树的遍历: 给你一棵树的先......
  • hdu1400/acwing 291 Mondriaan's Dream
    题意描述:给定一块n*m的区域,用1*2的长方形填充,长方形可以横着或竖着摆,问一共有多少种填充方案具体思路:题意没什么好说的,简单易懂,很经典的一类状态压缩问题(在棋盘中求填充方案)。观察数据,满足n,m都比较小,但是搜索的复杂度大到无法接受,考虑使用状态压缩求解此类问题......
  • [HDU4117] GRE
    RecentlyGeorgeispreparingfortheGraduateRecordExaminations(GREforshort).Obviouslythemostimportantthingisrecitingthewords.NowGeorgeisworkingonawordlistcontaining\(N\)words.Hehassopooramemorythatitistoohardforhim......
  • HDU - 7187-Slipper
    HDU-7187-Slipper(最短路、建图优化)题意:给出n个结点,n-1条无向边,经过每条边的代价为w,以结点1为根节点的树,对于相差k层的结点,可以花费代价p抵达,问结点s到t的最短路径。分析:考虑对于每层的每个点建立到相差k层的点的边,极端情况为$O(n^2)$的复杂度,需要优化。考虑对于每层......
  • HDU - 2844 - coins
    HDU-2844-coins(多重背包)题意:大壮想买东西,他有n种不同面值的硬币,每种有$c_i$个,他不想找零,也不想买超过价值m的东西,问他有多少种支付方式。$n(1≤n≤100),m(m≤100000)$分析:可以发现m的范围不大,直接在m中遍历。转化为给定一个容量为m的背包,问装入不同方案时,不同......