UVA-10859 Placing Lampposts
2017-10-16 15:05
295 查看
题目大意:
有一个无向无环图, 现在要选出一些点, 会覆盖和选出的点相连的边. 先要求选出的点最少的情况下, 被覆盖两次的边最多, 输出选出的点数, 被覆盖两次的边数和被覆盖一次的边数.
这个题, 怎么说呢, 很好....
其实题目说的无向无环图就是森林, 而求最小灯数的情况下最大化被覆盖两次的边, 转换一下就是最小灯数的情况下最小化只被覆盖一次的边.
那么我们设灯数是x, 只被覆盖一次的边为b, 那么我们只要最小化w=Mx+b即可, 其中M取一个大一点的数( 比方说2333 ).
答案就是ans/M, m-ans%M, ans%M.
那么就可以树形dp了.
首先刘汝佳设的状态是dp( i , 0/1 ), 即dp到i号点, 它的父亲放灯或者不放灯的最小w, 转移请看隔壁大保健的博客, 用记忆化搜索即可.
代码如下:
然后我看到了一个很棒棒的dp, 和我一开始一样的思路( 没写是因为没想到转移/捂脸 ):
设dp( i , 0/1 )表示第i个点, 放或者不放的最小w.
转移则dp( i , 0 )=Σdp( son , 1 )+1; dp( i , 1 )=Σmin( dp( son , 1 ) , dp( son , 0 )+1 ).
就不用记忆化搜索了, 普通树形dp的dfs就可以了.
是不是很棒棒?
代码如下:
有一个无向无环图, 现在要选出一些点, 会覆盖和选出的点相连的边. 先要求选出的点最少的情况下, 被覆盖两次的边最多, 输出选出的点数, 被覆盖两次的边数和被覆盖一次的边数.
这个题, 怎么说呢, 很好....
其实题目说的无向无环图就是森林, 而求最小灯数的情况下最大化被覆盖两次的边, 转换一下就是最小灯数的情况下最小化只被覆盖一次的边.
那么我们设灯数是x, 只被覆盖一次的边为b, 那么我们只要最小化w=Mx+b即可, 其中M取一个大一点的数( 比方说2333 ).
答案就是ans/M, m-ans%M, ans%M.
那么就可以树形dp了.
首先刘汝佳设的状态是dp( i , 0/1 ), 即dp到i号点, 它的父亲放灯或者不放灯的最小w, 转移请看隔壁大保健的博客, 用记忆化搜索即可.
代码如下:
//made by Crazy01 #include<queue> #include<math.h> #include<stdio.h> #include<string.h> #include<stdlib.h> #include<iostream> #include<algorithm> #define inf 1<<30 #define ll long long #define db double #define c233 cout<<"233"<<endl #define mem(s) memset(s,0,sizeof(s)) #define max(a,b) ((a)>(b)?(a):(b)) #define min(a,b) ((a)<(b)?(a):(b)) #define M 2333 const int N=1050; using namespace std; bool v [2]; int nxt[N<<1],to[N<<1],head ,dp [2]; int n,m,T,maxe,ans; inline int gi(){ int x=0,res=1;char ch=getchar(); while(ch>'9'||ch<'0'){if(ch=='-')res*=-1;ch=getchar();} while(ch<='9'&&ch>='0')x=(x<<1)+(x<<3)+ch-48,ch=getchar(); return x*res; } void clear(){ mem(v); mem(head); maxe=0; ans=0; } void build(int a,int b){ nxt[++maxe]=head[a]; to[maxe]=b; head[a]=maxe; } void init(){ n=gi(); m=gi(); for(int i=1;i<=m;i++){ int a=gi(),b=gi(); build(a,b); build(b,a); } } int dfs(int x,int j,int fa){ if(v[x][j])return dp[x][j]; v[x][j]=1; int ret=M; for(int i=head[x];i;i=nxt[i]){ int u=to[i]; if(u==fa)continue; ret+=dfs(u,1,x); } if(fa!=-1&&j==0)ret++; if(j==1||fa==-1){ int tmp=0; for(int i=head[x];i;i=nxt[i]){ int u=to[i]; if(u==fa)continue; tmp+=dfs(u,0,x); } if(fa!=-1)tmp++; ret=min(ret,tmp); } return dp[x][j]=ret; } void work(){ for(int i=0;i<n;i++) if(!v[i][0])ans+=dfs(i,0,-1); printf("%d %d %d\n",ans/M,m-ans%M,ans%M); } int main(){ T=gi(); while(T--){ clear(); init(); work(); } return 0; }
然后我看到了一个很棒棒的dp, 和我一开始一样的思路( 没写是因为没想到转移/捂脸 ):
设dp( i , 0/1 )表示第i个点, 放或者不放的最小w.
转移则dp( i , 0 )=Σdp( son , 1 )+1; dp( i , 1 )=Σmin( dp( son , 1 ) , dp( son , 0 )+1 ).
就不用记忆化搜索了, 普通树形dp的dfs就可以了.
是不是很棒棒?
代码如下:
//made by Crazy01 #include<queue> #include<math.h> #include<stdio.h> #include<string.h> #include<stdlib.h> #include<iostream> #include<algorithm> #define inf 1<<30 #define ll long long #define db double #define c233 cout<<"233"<<endl #define mem(s) memset(s,0,sizeof(s)) #define max(a,b) ((a)>(b)?(a):(b)) #define min(a,b) ((a)<(b)?(a):(b)) const int N=1050; const int M=2333; using namespace std; bool v ; int nxt[N<<1],to[N<<1],head ,dp [2]; int n,m,T,maxe,ans; inline int gi(){ int x=0,res=1;char ch=getchar(); while(ch>'9'||ch<'0'){if(ch=='-')res*=-1;ch=getchar();} while(ch<='9'&&ch>='0')x=(x<<1)+(x<<3)+ch-48,ch=getchar(); return x*res; } void clear(){ mem(v); mem(dp); mem(head); maxe=0; ans=0; } void build(int a,int b){ nxt[++maxe]=head[a]; to[maxe]=b; head[a]=maxe; } void init(){ n=gi(); m=gi(); for(int i=1;i<=m;i++){ int a=gi(),b=gi(); build(a,b); build(b,a); } } void dfs(int x,int fa){ dp[x][1]=M; v[x]=1; for(int i=head[x];i;i=nxt[i]){ int u=to[i]; if(u==fa)continue; dfs(u,x); dp[x][0]+=dp[u][1]+1; dp[x][1]+=min(dp[u][1],dp[u][0]+1); } } void work(){ for(int i=0;i<n;i++) if(!v[i]){ dfs(i,-1); ans+=min(dp[i][0],dp[i][1]); } printf("%d %d %d\n",ans/M,m-ans%M,ans%M); } int main(){ T=gi(); while(T--){ clear(); init(); work(); } return 0; }
相关文章推荐
- Uva 10859 - Placing Lampposts 树形dp
- UVa 10859 Placing Lampposts (树形DP)
- UVA10859 Placing Lampposts
- UVA 10859 Placing Lampposts 树形dp(水
- Uva-10859-Placing Lampposts
- UVA 10859 Placing Lampposts (动态规划)
- uva 10859 - Placing Lampposts(树形dp)
- Uva - 10859 - Placing Lampposts(树形dp)
- uva 10859 Placing Lampposts (树形dp)
- 【UVA10859】Placing Lampposts
- UVa 10859 Placing Lampposts / 树形DP
- UVa 10859 Placing Lampposts
- Placing Lampposts UVA - 10859(树形dp)
- UVA 10859 Placing Lampposts(树上dp)
- UVA 10859 Placing Lampposts(记忆化搜索)
- UVA 10859 Placing Lampposts 树型DP -
- [动态规划] 放置街灯 Uva 10859 - Placing Lampposts
- UVA--10859--Placing Lampposts--DP
- UVa:10859 Placing Lampposts(树形DP)
- UVA 10859 Placing Lampposts