树形dp系列
hdu 1520,poj2342
Anniversary party
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 12664 Accepted Submission(s): 5106
L K
It means that the K-th employee is an immediate supervisor of the L-th employee. Input is ended with the line
0 0
有搞并查集的,麻烦了。树形dp就行了。
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<algorithm> 5 #define clr(x) memset(x,0,sizeof(x)) 6 #define clr_1(x) memset(x,-1,sizeof(x)) 7 using namespace std; 8 const int N=1e4+10; 9 struct edg 10 { 11 int next,to; 12 }edge[N*2]; 13 int head[N],ecnt; 14 int dp[N][2],value[N],fa[N]; 15 void addedge(int u,int v) 16 { 17 edge[++ecnt]=(edg){head[u],v}; 18 head[u]=ecnt; 19 return ; 20 } 21 void dfs(int u,int pre) 22 { 23 dp[u][0]=dp[u][1]=0; 24 for(int i=head[u];i!=-1;i=edge[i].next) 25 { 26 if(edge[i].to!=pre) 27 { 28 dfs(edge[i].to,u); 29 dp[u][0]+=max(dp[edge[i].to][1],dp[edge[i].to][0]); 30 dp[u][1]+=dp[edge[i].to][0]; 31 } 32 } 33 dp[u][1]+=value[u]; 34 return ; 35 } 36 int main() 37 { 38 int n,u,v,root,m; 39 while(scanf("%d",&n)!=EOF && n) 40 { 41 for(int i=1;i<=n;i++) 42 scanf("%d",&value[i]); 43 clr_1(head); 44 ecnt=0; 45 clr(fa); 46 while(scanf("%d%d",&u,&v) && u|v) 47 { 48 addedge(v,u); 49 addedge(u,v); 50 fa[u]=v; 51 } 52 for(int i=1;i<=n;i++) 53 if(fa[i]==0) 54 { 55 root=i; 56 break; 57 } 58 dfs(root,0); 59 printf("%d\n",max(dp[root][0],dp[root][1])); 60 } 61 return 0; 62 }
hdu 2196
Computer
Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 31015 Accepted Submission(s): 3902
Hint: the example input is corresponding to this graph. And from the graph, you can see that the computer 4 is farthest one from 1, so S1 = 3. Computer 4 and 5 are the farthest ones from 2, so S2 = 2. Computer 5 is the farthest one from 3, so S3 = 3. we also get S4 = 4, S5 = 4.
1 #include<bits/stdc++.h> 2 #define clr(x) memset(x,0,sizeof(x)) 3 #define clr_1(x) memset(x,-1,sizeof(x)) 4 #define LL long long 5 #define mod 1000000007 6 using namespace std; 7 const int N=1e4+10; 8 struct edg 9 { 10 int next,to,cost; 11 }edge[N*2]; 12 int head[N],ecnt,allmax[N],maxpt[N],pt[N],maxptsec[N]; 13 void addedge(int u,int v,int cost) 14 { 15 edge[++ecnt]=(edg){head[u],v,cost}; 16 head[u]=ecnt; 17 return ; 18 } 19 int n,m,k,p,l; 20 void dfs1(int u,int pre) 21 { 22 maxpt[u]=maxptsec[u]=0; 23 pt[u]=0; 24 for(int i=head[u];i!=-1;i=edge[i].next) 25 if(edge[i].to!=pre) 26 { 27 dfs1(edge[i].to,u); 28 if(maxpt[edge[i].to]+edge[i].cost>maxpt[u]) 29 { 30 maxpt[u]=maxpt[edge[i].to]+edge[i].cost; 31 pt[u]=edge[i].to; 32 } 33 } 34 for(int i=head[u];i!=-1;i=edge[i].next) 35 if(edge[i].to!=pre) 36 { 37 if(maxpt[edge[i].to]+edge[i].cost>maxptsec[u] && pt[u]!=edge[i].to) 38 { 39 maxptsec[u]=maxpt[edge[i].to]+edge[i].cost; 40 } 41 } 42 return ; 43 } 44 void dfs2(int u,int pre,int ans) 45 { 46 allmax[u]=max(ans,maxpt[u]); 47 if(ans>=maxpt[u]) 48 { 49 for(int i=head[u];i!=-1;i=edge[i].next) 50 { 51 if(edge[i].to!=pre) 52 { 53 dfs2(edge[i].to,u,ans+edge[i].cost); 54 } 55 } 56 } 57 else 58 { 59 for(int i=head[u];i!=-1;i=edge[i].next) 60 { 61 if(edge[i].to!=pre) 62 { 63 if(pt[u]==edge[i].to) 64 dfs2(edge[i].to,u,max(ans,maxptsec[u])+edge[i].cost); 65 else 66 dfs2(edge[i].to,u,maxpt[u]+edge[i].cost); 67 } 68 } 69 } 70 return ; 71 } 72 int main() 73 { 74 while(scanf("%d",&n)!=EOF) 75 { 76 clr_1(head); 77 ecnt=0; 78 for(int i=2;i<=n;i++) 79 { 80 scanf("%d%d",&m,&k); 81 addedge(i,m,k); 82 addedge(m,i,k); 83 } 84 allmax[0]=0; 85 dfs1(1,1); 86 dfs2(1,1,0); 87 for(int i=1;i<=n;i++) 88 printf("%d\n",allmax[i]); 89 } 90 return 0; 91 }
描述
几乎整个Byteland 王国都被森林和河流所覆盖。小点的河汇聚到一起,形成了稍大点的河。就这样,所有的河水都汇聚并流进了一条大河,最后这条大河流进了大海。这条大河的入海口处有一个村庄——Bytetown。
在Byteland国,有n个伐木的村庄,这些村庄都座落在河边。目前在Bytetown,有一个巨大的伐木场,它处理着全国砍下的所有木料。木料被砍下后,顺着河流而被运到Bytetown的伐木场。Byteland 的国王决定,为了减少运输木料的费用,再额外地建造k个伐木场。这k个伐木场将被建在其他村庄里。这些伐木场建造后,木料就不用都被送到Bytetown了,它们可以在 运输过程中第一个碰到的新伐木场被处理。显然,如果伐木场座落的那个村子就不用再付运送木料的费用了。它们可以直接被本村的伐木场处理。
注:所有的河流都不会分叉,形成一棵树,根结点是Bytetown。
国王的大臣计算出了每个村子每年要产多少木料,你的任务是决定在哪些村子建设伐木场能获得最小的运费。其中运费的计算方法为:每一吨木料每千米1分钱。
编一个程序:
1.从文件读入村子的个数,另外要建设的伐木场的数目,每年每个村子产的木料的块数以及河流的描述。
2.计算最小的运费并输出。
格式
输入格式
第一行包括两个数n(2<=n<=100),k(1<=k<=50,且k<=n)。n为村庄数,k为要建的伐木场的数目。除了Bytetown 外,每个村子依次被命名为 1,2,3……n,Bytetown被命名为0。
接下来n行,每行3个整数:
wi——每年 i 村子产的木料的块数。(0<=wi<=10000)
vi——离 i 村子下游最近的村子。(即 i 村子的父结点)(0<=vi<=n)
di——vi 到 i 的距离(千米)。(1<=di<=10000)
保证每年所有的木料流到bytetown 的运费不超过2000,000,000分
50%的数据中n不超过20。
输出格式
输出最小花费,精确到分。
样例1
样例输入1
4 2
1 0 1
1 1 10
10 2 5
1 2 3
样例输出1
4
1 #include<bits/stdc++.h> 2 #define clr(x) memset(x,0,sizeof(x)) 3 #define clr_1(x) memset(x,-1,sizeof(x)) 4 #define LL long long 5 #define mod 1000000007 6 using namespace std; 7 const int N=2e2+10; 8 int f[N][N][N],fa[N]; 9 int dis[N],ans; 10 struct edg 11 { 12 int next,to,val; 13 }edge[N*2]; 14 int head[N],ecnt,sonnum[N]; 15 int w[N],n,m,k,t,l,v; 16 void addedge(int u,int v,int val) 17 { 18 edge[++ecnt]=(edg){head[u],v,val}; 19 head[u]=ecnt; 20 return ; 21 } 22 void dfs1(int u,int pre,int dist) 23 { 24 dis[u]=dist; 25 fa[u]=pre; 26 if(head[u]!=-1 && edge[head[u]].to==pre) 27 head[u]=edge[head[u]].next; 28 for(int i=head[u];i!=-1;i=edge[i].next) 29 { 30 if(edge[i].next!=-1 && edge[edge[i].next].to==pre) 31 edge[i].next=edge[edge[i].next].next; 32 dfs1(edge[i].to,u,dist+edge[i].val); 33 } 34 return ; 35 } 36 int findson(int u,int i) 37 { 38 sonnum[u]=0; 39 sonnum[u]+=((head[u]==-1)?0:findson(edge[head[u]].to,head[u])); 40 sonnum[u]+=((edge[i].next==-1)?0:findson(edge[edge[i].next].to,edge[i].next)); 41 return sonnum[u]+1; 42 } 43 int dfs2(int u,int to,int pk,int i) 44 { 45 if(f[u][to][pk]!=-1) return f[u][to][pk]; 46 if(pk>sonnum[u]) return 0; 47 int ans=-1; 48 int brother,son; 49 //不选u,0点也包括因为他也不建伐木场。 50 for(int j=0;j<=pk;j++) 51 { 52 son=(head[u]==-1)?0:dfs2(edge[head[u]].to,to,j,head[u]); 53 brother=(edge[i].next==-1)?0:dfs2(edge[edge[i].next].to,to,pk-j,edge[i].next); 54 if(ans==-1||ans>son+brother) 55 ans=son+brother; 56 } 57 if(ans==-1) 58 ans=w[u]*(dis[u]-dis[to]); 59 else 60 ans+=w[u]*(dis[u]-dis[to]); 61 //选u 62 if(pk>0 && u!=0) 63 { 64 for(int j=0;j<pk;j++) 65 { 66 son=(head[u]==-1)?0:dfs2(edge[head[u]].to,u,j,head[u]); 67 brother=(edge[i].next==-1)?0:dfs2(edge[edge[i].next].to,to,pk-j-1,edge[i].next); 68 if(ans>son+brother) 69 ans=son+brother; 70 } 71 } 72 return f[u][to][pk]=ans; 73 } 74 int main() 75 { 76 scanf("%d%d",&n,&k); 77 clr_1(head); 78 ecnt=0; 79 for(int i=1;i<=n;i++) 80 { 81 scanf("%d%d%d",&w[i],&v,&l); 82 addedge(i,v,l); 83 addedge(v,i,l); 84 } 85 clr(dis); 86 edge[0].next=-1; 87 dfs1(0,0,0); 88 findson(0,0); 89 clr_1(f); 90 printf("%d\n",dfs2(0,0,k,0)); 91 return 0; 92 }
codevs 1787
网络收费
2006年NOI全国竞赛