$Poj3585\\ Accumulation Degree$ 树形$DP/$二次扫描与换根法

匿名 (未验证) 提交于 2019-12-02 23:42:01

Poj

Description

有一个树形的水系,由n-1条河道与n个交叉点组成.每条河道有一个容量,联结x与y的河道容量记为c(x,y),河道的单位时间水量不能超过它的容量.有一个结点是整个水系的发源地,可以源源不断地流出水,为源点.树中度为1的点是入海口,可以吸收无限多的水,为汇点.待整个水系稳定时,每条河道中的水都以单位时间固定的水量流向固定的方向.整个水系的流量就定义为源点单位时间发出的水量.

求哪个点作为源点时,整个水系的流量最大.

Sol

最朴素的做法就是枚举源点,再树形DP,更新答案.复杂度是O(n2)的,不能接受.

推想:某点为源点时的流量可以由其他点为源点时的流量推出

d[x]表示x的度,f1[x]表示以x为根的树的最大流量,f2[x]表示以x为源点时水系的最大流量,y是x的子结点

首先任意选取一个点作为源点(root),一次树形DP算出所有的f1[x]

现在已知f2[x],可以推出f2[y]:

f2[y]包括两个部分:

1.流向x,(没错x由父变子hhh),这部分的流量:

2.流向原来就是它的子结点的点,这部分的流量就是f1[y]

over!

Code

 1 #include<iostream>  2 #include<cstdio>  3 #include<cstring>  4 #include<vector>  5 #define Rg register  6 #define il inline  7 #define mem(a,b) memset(a,b,sizeof(a));  8 #define go(i,a,b) for(Rg int i=a;i<=b;++i)  9 using namespace std; 10 il int read() 11 { 12     int x=0,y=1;char c=getchar(); 13     while(c<'0'||c>'9'){if(c=='-')y=-1;c=getchar();} 14     while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+c-'0';c=getchar();} 15     return x*y; 16 } 17 const int N=200001; 18 int T,n,ans,d[N],f1[N],f2[N]; 19 bool vis[N]; 20 struct node{int y,w;}; 21 vector<node> c[N]; 22 il void init() 23 { 24     ans=0; 25     mem(vis,0);mem(d,0);mem(f1,0);mem(f2,0); 26     go(i,1,n)c[i].clear(); 27 } 28 il void dp1(int x) 29 { 30     vis[x]=1; 31     int hhh=c[x].size()-1; 32     go(i,0,hhh) 33     { 34         int y=c[x][i].y,w=c[x][i].w; 35         if(vis[y])continue; 36         dp1(y); 37         if(d[y]==1)f1[x]+=w; 38         else f1[x]+=min(f1[y],w); 39     } 40 } 41 il void dp2(int x) 42 { 43     vis[x]=1; 44     int hhh=c[x].size()-1;if(hhh<0)return; 45     go(i,0,hhh) 46     { 47         int y=c[x][i].y,w=c[x][i].w; 48         if(vis[y])continue; 49         if(d[x]==1)f2[y]=f1[y]+w; 50         else f2[y]=f1[y]+min(f2[x]-min(f1[y],w),w); 51         dp2(y); 52     } 53 } 54 int main() 55 { 56     T=read(); 57     while(T--) 58     { 59         n=read();init(); 60         go(i,1,n-1) 61         { 62             int x=read(),y=read(),z=read(); 63             c[x].push_back((node){y,z});c[y].push_back((node){x,z}); 64             ++d[x],++d[y]; 65         } 66         dp1(1); 67                 f2[1]=f1[1];mem(vis,0); 68         dp2(1); 69         go(i,1,n)ans=max(ans,f2[i]); 70         printf("%d\n",ans); 71     } 72     return 0; 73 } 74         
View Code

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!