题意:给定一个图,节点可以放灯,要求用最少的灯覆盖所有的边(每盏灯能覆盖该节点邻接的边),满足条件的同时求该前提下尽量多的被两盏灯照亮的边数

条件二转化为求尽量少的被一盏灯照亮的边数,两个条件都是求min,我们需要构造一个条件一取决定性作用的式子,

令\(f(a,b)=Ma+b\),其中\(a\)为条件一的最优解,\(M\)为一个足够大的数,以至于\(b\)的最大值都小于\(M\)(更精确的应该是\(M>b_{max}-a_{min}\)),那么\(b\)为满足\(a\)前提下的最优解,所以我们就是在图上DP求解这条式子的min,两个系数分别对应不同的解

有一些实现上的细节需要注意,dp方程应该设\(dp[i][j]\):父节点灯\([j==1]\)与否的情况下\(i\)子树及沿向父亲的边的最优解

为什么点灯要从父亲那里设?因为如果设为子树根的情况的话,遍历森林求解ans时会十分繁琐

而父亲节点只要设置一个0的不存在的根,一切都会十分好办

不过这还是取决于编写习惯

还有一个要小心的地方是若父亲情况为0时,子树的根节点也是可以为0的,因为父节点可以是不存在的根

ChromeOS用某IDE无法注释中文,凑合看

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<string>
#include<vector>
#include<stack>
#include<queue>
#include<set>
#include<map>
#define rep(i,j,k) for(register int i=j;i<=k;i++)
#define rrep(i,j,k) for(register int i=j;i>=k;i--)
#define erep(i,u) for(register int i=head[u];~i;i=nxt[i])
#define iin(a) scanf("%d",&a)
#define lin(a) scanf("%lld",&a)
#define din(a) scanf("%lf",&a)
#define s0(a) scanf("%s",a)
#define s1(a) scanf("%s",a+1)
#define print(a) printf("%lld",(ll)a)
#define enter putchar('\n')
#define blank putchar(' ')
#define println(a) printf("%lld\n",(ll)a)
#define IOS ios::sync_with_stdio(0)
using namespace std;
const int maxn = 1e4+11;
const double eps = 1e-10;
typedef long long ll;
const int oo = 0x3f3f3f3f;
ll read(){
ll x=0,f=1;register char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
ll dp[maxn][2];
int to[maxn<<1],nxt[maxn<<1],head[maxn],tot;
void init(){
memset(head,-1,sizeof head);
tot=0;
}
void add(int u,int v){
to[tot]=v;nxt[tot]=head[u];head[u]=tot++;
swap(u,v);
to[tot]=v;nxt[tot]=head[u];head[u]=tot++;
}
ll M;
// bool isleaf(int u,int fa){
// int cnt=0;
// erep(i,u){
// int v=to[i];
// if(v==fa)continue;
// cnt++;
// if(cnt==1)return 0;
// }
// return 1;
// }
// int deg[maxn];
// ll DP(int u,int fa,int flag){
// if(~dp[u][flag]) return dp[u][flag];
// if(isleaf(u,fa)) return dp[u][flag]=flag*M;
// ll ans=flag*M;
// if(flag==1) erep(i,u){
// int v=to[i];
// if(v==fa)continue;
// ans+=min(DP(v,u,0)+1,DP(v,u,1));
// }else erep(i,u){
// int v=to[i];
// if(v==fa)continue;
// ans+=DP(v,u,1)+1;
// }
// return dp[u][flag]=ans;
// }
bool vis[maxn][2];
ll DP(int u,int fa,int flag){//fujiedianfangdengwei true
if(vis[u][flag])return dp[u][flag];
vis[u][flag]=1; //ru guo u shi gen na ye ke yi bu fang deng jiagen wei 0 gen yewei 0
if(flag==0){
dp[u][0]=M+bool(fa!=0);//virtual root
erep(i,u){
int v=to[i];
if(v==fa)continue;
dp[u][0]+=DP(v,u,1);
}
ll tmp=1ll<<60;
if(fa==0){
tmp=0;
erep(i,u){
int v=to[i];
if(v==fa)continue;
tmp+=DP(v,u,0);
}
}
return dp[u][0]=min(dp[u][0],tmp);//ok
}else{
// dp[u][1]+=min(DP(v,u,1),DP(v,u,0));//cannot dfs
ll tmp1=M;//u fangdeng
erep(i,u){
int v=to[i];
if(v==fa)continue;
tmp1+=DP(v,u,1);
}
ll tmp2=1;//bufangdeng
erep(i,u){
int v=to[i];
if(v==fa)continue;
tmp2+=DP(v,u,0);
}
return dp[u][1]=min(tmp1,tmp2);
}
}
int main(){
int T=read();
while(T--){
init();
memset(dp,-1,sizeof dp);
memset(vis,0,sizeof vis);
int n=read();
int m=read();
rep(i,1,m){
int u=read();u++;
int v=read();v++;
add(u,v);
}
M=2333;
ll ans=0;
rep(i,1,n){
if(!vis[i][0]){
ans+=DP(i,0,0);
}
}
printf("%lld %lld %lld\n",ans/M,m-(ans%M),ans%M);
}
return 0;
}

UVA - 10589 构造最优化函数 DP好题的更多相关文章

  1. 贪心/构造/DP 杂题选做Ⅱ

    由于换了台电脑,而我的贪心 & 构造能力依然很拉跨,所以决定再开一个坑( 前传: 贪心/构造/DP 杂题选做 u1s1 我预感还有Ⅲ(欸,这不是我在多项式Ⅱ中说过的原话吗) 24. P5912 ...

  2. 贪心/构造/DP 杂题选做Ⅲ

    颓!颓!颓!(bushi 前传: 贪心/构造/DP 杂题选做 贪心/构造/DP 杂题选做Ⅱ 51. CF758E Broken Tree 讲个笑话,这道题是 11.3 模拟赛的 T2,模拟赛里那道题的 ...

  3. DP刷题记录(持续更新)

    DP刷题记录 (本文例题目前大多数都选自算法竞赛进阶指南) TYVJ1071 求两个序列的最长公共上升子序列 设\(f_{i,j}\)表示a中的\(1-i\)与b中色\(1-j\)匹配时所能构成的以\ ...

  4. DP百题练(二)

    目录 DP百题练(二) 区间 DP NOI1995 石子合并 IOI1998 Polygon CH5302 金字塔 USACO06FEB Treats for the Cows G/S LG1043 ...

  5. ACM :漫漫上学路 -DP -水题

    CSU 1772 漫漫上学路 Time Limit: 1000MS   Memory Limit: 131072KB   64bit IO Format: %lld & %llu Submit ...

  6. [poj2247] Humble Numbers (DP水题)

    DP 水题 Description A number whose only prime factors are 2,3,5 or 7 is called a humble number. The se ...

  7. poj 3254 状压dp入门题

    1.poj 3254  Corn Fields    状态压缩dp入门题 2.总结:二进制实在巧妙,以前从来没想过可以这样用. 题意:n行m列,1表示肥沃,0表示贫瘠,把牛放在肥沃处,要求所有牛不能相 ...

  8. UVA 11137 Ingenuous Cubrency(dp)

    Ingenuous Cubrency 又是dp问题,我又想了2 30分钟,一点思路也没有,最后又是看的题解,哎,为什么我做dp的题这么烂啊! [题目链接]Ingenuous Cubrency [题目类 ...

  9. POJ 1155 TELE 背包型树形DP 经典题

    由电视台,中转站,和用户的电视组成的体系刚好是一棵树 n个节点,编号分别为1~n,1是电视台中心,2~n-m是中转站,n-m+1~n是用户,1为root 现在节点1准备转播一场比赛,已知从一个节点传送 ...

随机推荐

  1. Web网站的几个QPS

    评价一个网站的"大小",处于视角的不同,有很多种衡量的方法,类似文章数,页面数之类的数据非常明显,也没有什么可以争议的.但对于并发来说,争议非常之多,这里就从一个技术的角度开始,谈 ...

  2. list 的扩展

    数据挖掘中会遇到添加多个新的特征s,对一个feature = list()来说, 除了可以用 feature.append('xx') # 在尾部添加一个特征 feature.extend(['xx' ...

  3. ubuntu下安装配置apache2(含虚拟主机配置)

    在Ubuntu14.14中安装apache 安装指令: sudo apt-get install apache2 安装结束后: 产生的启动和停止文件是: /etc/init.d/apache2 启动: ...

  4. Robot Framework - 基础关键字 BuiltIn 库(二)

    本篇教程,我们继续接着上篇内容进行讲解,我们本节教程讲解的是Robot Framework 机器人框架中的变量中使用判断.字符串的拼接.Evaluate的用法.调用Python文件.条件分支语句.以及 ...

  5. 现代C++学习笔记之一资料篇(C++ 11)

    最近看网上一些开源的源代码,发现尽多不认识的符号,好吧.开始学习新的C++. C++经典书籍 C++ Primer,第五版开始有了对C++ 11的讲解 C++ Primer Plus,第六版有对C++ ...

  6. POJ2253 Frogger(spfa变形)

    Description Freddy Frog is sitting on a stone in the middle of a lake. Suddenly he notices Fiona Fro ...

  7. 「TJOI2015」线性代数

    题目链接 戳我 \(Describe\) 题目描述 为了提高智商,\(ZJY\)开始学习线性代数.她的小伙伴菠萝给她出了这样一个问题:给定一个\(n×n\)的矩阵\(B\)和一个\(1×n\)的矩阵\ ...

  8. java并发编程(更新)

    概念理解:①串行程序②并发程序: 线程安全问题: 同一进程中的所有线程共享进程中的内存地址空间.如果没有明确的同步机制来管理共享数据,那么当一个线程正在使用某个变量时,另一个线程可能同时访问这个变量, ...

  9. 美团Java实习面试经历(拿到Offer)

      美团我是在拉勾网上投的简历,之前也投过一次,简历都没通过删选,后来让学姐帮我改了一下简历,重新投另一个部门,获得了面试机会.10月23日中午HR打电话过来预约了下午4点半面试,说会在线写代码,让我 ...

  10. spring boot 第一个Dome

    1.创建Maven项目 按照下面的步骤 项目创建完成后的目录结构 2. 参照Spring boot官方文档修改pom.xml 修改 maven编译的jdk版本 将spring boot设置为 pare ...