Cattle guest CSP-S improve the training camp before the group 1 T2: is the love and the extent of urban congestion

Topic Link


Title Description

National is the love resides there \ (n \) cities, there are between these cities and city \ (n-1 \) highway connecting, and to ensure that these cities directly or indirectly connected between any two.

We define the distance between the two cities on the total number of unique simple path road between the two cities.

When is the love located on the \ (x \) when the city, from the city \ (x \) distance of not more than \ (k \) of the city people will think that is the best in the world love cute!

Think is the best in the world love lovely people to decide where is the love lovely city to visit is the love. We define the degree of congestion in these cities is as follows:

  • From the city \ (x \) distance of not more than \ (k \) cities of people reach the city \ (x \) the number of times the city passes.

E.g:

Suppose \ (K = 2 \) , where is the city is love \ (1 \) No. city, when the tree structure as shown above, is affected by urban \ (1,2,3,4,5 \) , because the five cities from \ (1 \) from the city's numbers are: \ (0,1,2,2,2 \) , so these five cities will think love is the best in the world.

  • \ (1 \) No. city to \ (1 \) No. city after the \ (1 \) No. city.
  • \ (2 \) No. city to \ (1 \) No. city after the \ (1 \) number, \ (2 \) No. city.
  • \ (3 \) No. city to \ (1 \) No. city after the \ (1 \) number, \ (2 \) number, \ (3 \) No. city.
  • \ (4 \) No. city to \ (1 \) No. city after the \ (1 \) number, \ (2 \) number, \ (4 \) No. city.
  • \ (5 \) No. city to \ (1 \) No. city after the \ (1 \) number, \ (2 \) number, \ (5 \) No. city.

Therefore, the degree of congestion is the No. 1 city congestion No. 5,2 city is crowding No. 4,3, 4, 5, the city is 1.

Now small w want to ask you when is the love in turn located on 1,2,3,4,5 ... n cities, cities in the number of people who think that love is the best in the world, as well as affected urban the degree of congestion of the product, due to the large figure will be, so ask you to think the output is the best in the world love the extent of urban congestion product \ (\ mod + 7 \ 10 ^ 9) results after.

Output Description:

Output two lines.

The first row of n integer representing when is the love in turn located on 1,2,3,4,5.. .N cities, cities in the number of people who think that love is the best in the world.

The second row of n integer representing when is the love in turn located on 1,2,3,4,5.. .N cities, urban congestion level of the affected product $ \ mod results after 10 ^ 9 + 7 $ .


80 Violence: \ (O (the n-^ 2) \) enumerate what vertex, just mess things up just fine

Paste Point Code: (P2 processing chain is the case)

namespace P1{
    int ans1[N],ans2[N];
    int dfs(int rt,int x,int f,int dis){
        if(dis>K)return 0;int sz=1;
        for(int i=0;i<edge[x].size();i++){
            int y=edge[x][i];
            if(y==f)continue;
            sz=sz+dfs(rt,y,x,dis+1);
        }
        ans2[rt]=1ll*ans2[rt]*sz%P;
        return sz;
    }
    void solve(){
        for(int i=1;i<=n;i++)ans2[i]=1,ans1[i]=dfs(i,i,0,0);
        for(int i=1;i<n;i++)printf("%d ",ans1[i]);
        printf("%d\n",ans1[n]);
        for(int i=1;i<n;i++)printf("%d ",ans2[i]);
        printf("%d\n",ans2[n]);
        exit(0);
    }
}
int in[N];
namespace P2{
    int id[N],ans1[N],ans2[N];
    void pre_dfs(int x,int f,int cnt){
        id[cnt]=x;
        for(int i=0;i<edge[x].size();i++){
            int y=edge[x][i];
            if(y==f)continue;
            pre_dfs(y,x,cnt+1);
        }
    }
    int fac[N];
    void solve(){
        fac[0]=1;
        for(int i=1;i<=K+10;i++)fac[i]=1ll*fac[i-1]*i%P;
        int st;
        for(int i=1;i<=n;i++)
            if(in[i]==1){st=i;break;}
        pre_dfs(st,0,1);
        for(int i=1;i<=n;i++){
            int l=min(K,i-1),r=min(K,n-i);
            ans1[id[i]]=1+l+r;
            ans2[id[i]]=1ll*ans1[id[i]]*fac[l]%P*fac[r]%P;
        }
        for(int i=1;i<n;i++)printf("%d ",ans1[i]);printf("%d\n",ans1[n]);
        for(int i=1;i<n;i++)printf("%d ",ans2[i]);printf("%d\n",ans2[n]);
        exit(0);
    }
}

Correct answer: DP + 换根

Before hair over one root of the problem is relatively simple to change the title of the solution, just some simple analysis, this question is slightly more complicated, more things to consider.

First on the code:

#include<bits/stdc++.h>
#define debug(a) cout<<#a<<"="<<a<<endl
#define LL long long
using namespace std;
bool cur1;
const int N=100005,P=1e9+7;
int n,K;
vector<int>edge[N];
LL dp1[N][15],dp2[N][15];
LL kpow(LL x,LL y){
    LL res=1;
    while(y){
        if(y&1)res=res*x%P;
        x=x*x%P;
        y>>=1;
    }
    return res;
}
LL inv(LL x){return kpow(x,P-2);}//不方便预处理(1e9+7),现场求逆元 
void pre_dfs(int x,int f){
    dp1[x][0]=1;
    for(int i=0;i<=K;i++)dp2[x][i]=1;
    for(int i=0;i<edge[x].size();i++){
        int y=edge[x][i];
        if(y==f)continue;
        pre_dfs(y,x);
        for(int j=1;j<=K;j++){
            dp1[x][j]+=dp1[y][j-1]; //dp1[x][y]表示x子树里与x距离为y的城市个数
            dp2[x][j]=dp2[x][j]*dp2[y][j-1]%P; //dp2[x][y]表示x子树里当K=y时拥挤度的乘积
        }
    }
    LL sum=0;
    for(int i=0;i<=K;i++){
        sum+=dp1[x][i];
        dp2[x][i]=dp2[x][i]*sum%P;//乘上dp[x][i]中x这个点的拥挤度 
    }
}
void cut_dp(int rt1,int rt2){//当前rt1为rt2的父节点,要切断rt1和rt2的联系 
    for(int i=1;i<=K;i++)dp2[rt1][i]=dp2[rt1][i]*inv(dp2[rt2][i-1])%P;//除掉rt2子树里的拥挤度乘积 
    LL sum=0;
    for(int i=0;i<=K;i++){
        sum+=dp1[rt1][i];
        dp2[rt1][i]=dp2[rt1][i]*inv(sum)%P;
    }sum=0;//把rt1这个点的拥挤程度除掉,因为后面换根后会dp1会发生变化 
    for(int i=0;i<=K;i++){
        sum+=dp1[rt2][i];
        dp2[rt2][i]=dp2[rt2][i]*inv(sum)%P;
    }//把rt2的除掉 
    for(int i=1;i<=K;i++)dp1[rt1][i]-=dp1[rt2][i-1];//个数减掉 
}
void link_dp(int rt1,int rt2){//当前rt1和rt2为没有关系的两个点,要连接rt1和rt2,使得rt1为rt2的父节点 
    for(int i=1;i<=K;i++)dp1[rt1][i]+=dp1[rt2][i-1];
    LL sum=0;
    for(int i=0;i<=K;i++){
        sum+=dp1[rt1][i];
        dp2[rt1][i]=dp2[rt1][i]*sum%P;
    }sum=0;
    for(int i=0;i<=K;i++){
        sum+=dp1[rt2][i];
        dp2[rt2][i]=dp2[rt2][i]*sum%P;
    }
    for(int i=1;i<=K;i++)dp2[rt1][i]=dp2[rt1][i]*dp2[rt2][i-1]%P;
}//同理cut_dp,顺序稍有改变 
void change(int x,int y){// 当前x为y的父节点
    cut_dp(x,y);// 切断x与y的联系
    link_dp(y,x);//  将y作为父节点,x作为y的儿子,重新连接 y,x
}
LL ans1[N],ans2[N]; 
void dfs(int x,int f){
    for(int i=0;i<=K;i++)ans1[x]+=dp1[x][i];
    ans2[x]=dp2[x][K];//当前的dp1[x],dp2[x]都是以x为根时的结果,直接统计就是答案(统计方式的不同取决于定义的不同) 
    for(int i=0;i<edge[x].size();i++){
        int y=edge[x][i];
        if(y==f)continue;
        change(x,y);//换根 
        dfs(y,x);
        change(y,x);//换回来(还原现场) 
    }
}
bool cur2;
int main(){
//  printf("%lf",(&cur2-&cur1)/1024.0/1024);
    scanf("%d%d",&n,&K);
    for(int i=1,u,v;i<n;i++){
        scanf("%d%d",&u,&v);
        edge[u].push_back(v);
        edge[v].push_back(u);
    }
    pre_dfs(1,0);
    dfs(1,0);
    for(int i=1;i<n;i++)printf("%lld ",ans1[i]);printf("%lld\n",ans1[n]);
    for(int i=1;i<n;i++)printf("%lld ",ans2[i]);printf("%lld\n",ans2[n]);
    return 0;
}

In fact, look at the words of the comment on the same subject. .

Mainly involves a very common routines transducer root: \ (Cut \) and \ (Link \)

Popularize English words. . \ (Link \) : connector

In other root method:

A first stuffing is used as a root node points to give the whole tree each node \ (DP \) information and storing them. (Corresponding to code \ (pre \ _dfs \) )

Consider changing the root adjacent nodes, the root node is assumed to \ (X \) , then the whole teeth tree \ (DP \) information is \ (X \) constructed on the basis of the root, \ (Y \ ) node \ (x \) direct child node. We found that when the whole tree from the root node \ (x \) is converted to \ (y \) , the change of \ (dp \) information is actually very small, often only affects \ (x, y \) two nodes .

As shown, the current \ (x \) is \ (y \) father, we have to deal with the \ (x \) answer, and now want to change the root, the (y \) \ into the root.

Consider changing root into two operations performed:

  1. Cut \ (x \) and \ (y \) contact ( \ (Cut \) )

  2. Reconnection \ (X \) and \ (Y \) , so \ (Y \) is the \ (X \) is the father ( \ (Link \) )

So there is a method of substantially changing the root problem.

Specific details may be found in the code comments.

Guess you like

Origin www.cnblogs.com/tangzhiyang/p/11804691.html