• [poj3107/poj2378]Godfather/Tree Cutting树形dp


    题意:求树的重心(删除该点后子树最大的最小)

    解题关键:想树的结构,删去某个点后只剩下它的子树和原树-此树所形成的数,然后第一次dp求每个子树的节点个数,第二次dp求解答案即可。

    此题一开始一直T,后来加了输入挂才过,第一次见卡cin+关同步的题目。

    用scanf试了一下,也可以过,0.5s,看来cin关同步和scanf差距也是蛮大的。

    任何时候树形dp在dfs中做两次循环都是没必要的。只要了解是先序遍历和后序遍历,在一个for中处理即可。

    poj2378将改为n/2即可。

    优化:循环的部分少了 最终141ms

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 #include<cstdlib>
     5 #include<cmath>
     6 #include<iostream>
     7 #define inf 0x3f3f3f3f
     8 using namespace std;
     9 typedef long long ll;
    10 const int maxn=1e5+3;
    11 int head[maxn],tot,n;
    12 struct edge{
    13     int to;
    14     int nxt;
    15     int w;
    16 }e[maxn<<1];
    17 
    18 void add_edge(int u,int v,int w){
    19     e[tot].to=v;
    20     e[tot].w=w;
    21     e[tot].nxt=head[u];
    22     head[u]=tot++;
    23 }
    24 int dp[maxn<<2],cnt[maxn];
    25 
    26 void dfs(int u,int fa){
    27     cnt[u]=1;
    28     for(int i=head[u];i!=-1;i=e[i].nxt){
    29         int v=e[i].to;
    30         if(v==fa) continue;
    31         dfs(v,u);
    32         cnt[u]+=cnt[v];
    33         dp[u]=max(dp[u],cnt[v]);
    34     }
    35     dp[u]=max(n-cnt[u],dp[u]);
    36 }
    37 inline int read(){
    38     char k=0;char ls;ls=getchar();for(;ls<'0'||ls>'9';k=ls,ls=getchar());
    39     int x=0;for(;ls>='0'&&ls<='9';ls=getchar())x=(x<<3)+(x<<1)+ls-'0';
    40     if(k=='-')x=0-x;return x;
    41 }
    42 int main(){
    43     n=read();
    44     memset(head,-1,sizeof head);
    45     tot=0;
    46     int a,b;
    47     for(int i=0;i<n-1;i++){
    48         a=read();
    49         b=read();
    50         add_edge(a,b,1);
    51         add_edge(b,a,1);
    52     }
    53     dfs(1,-1);
    54     int ans=inf;
    55     for(int i=1;i<=n;i++){
    56         ans=min(ans,dp[i]);
    57     }
    58     bool flag=false;
    59     for(int i=1;i<=n;i++){
    60         if(dp[i]==ans){
    61             if(flag) printf(" ");
    62             printf("%d",i);
    63             flag=true;
    64         }
    65     }
    66     printf("
    ");
    67     return 0;
    68 }

    一:219ms

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 #include<cstdlib>
     5 #include<cmath>
     6 #include<iostream>
     7 #define inf 0x3f3f3f3f
     8 using namespace std;
     9 typedef long long ll;
    10 const int maxn=1e5+3;
    11 int head[maxn],tot,n;
    12 struct edge{
    13     int to;
    14     int nxt;
    15     int w;
    16 }e[maxn<<1];
    17 void add_edge(int u,int v,int w){
    18     e[tot].to=v;
    19     e[tot].w=w;
    20     e[tot].nxt=head[u];
    21     head[u]=tot++;
    22 }
    23 int dp[maxn<<2],cnt[maxn];
    24 void dfs(int u,int fa){
    25     cnt[u]=1;
    26     for(int i=head[u];i!=-1;i=e[i].nxt){
    27         int v=e[i].to;
    28         if(v==fa) continue;
    29         dfs(v,u);
    30         cnt[u]+=cnt[v];
    31     }
    32     dp[u]=n-cnt[u];
    33     for(int i=head[u];i!=-1;i=e[i].nxt){
    34         int v=e[i].to;
    35         if(v==fa) continue;
    36         dp[u]=max(dp[u],cnt[v]);
    37     }
    38 }
    39 
    40 inline int read(){
    41     char k=0;char ls;ls=getchar();for(;ls<'0'||ls>'9';k=ls,ls=getchar());
    42     int x=0;for(;ls>='0'&&ls<='9';ls=getchar())x=x*10+ls-'0';
    43     if(k=='-')x=0-x;return x;
    44 }
    45 int main(){
    46     //ios::sync_with_stdio(0);
    47     //cin.tie(0);
    48     //cout.tie(0);
    49     n=read();
    50     memset(head,-1,sizeof head);
    51     tot=0;
    52     int a,b;
    53     for(int i=0;i<n-1;i++){
    54         //scanf("%d%d",&a,&b);
    55         //cin>>a>>b;
    56         a=read();
    57         b=read();
    58         add_edge(a,b,1);
    59         add_edge(b,a,1);
    60     }
    61     dfs(1,-1);
    62     int ans=inf;
    63     for(int i=1;i<=n;i++){
    64         ans=min(ans,dp[i]);
    65     }
    66     bool flag=false;
    67     for(int i=1;i<=n;i++){
    68         if(dp[i]==ans){
    69             if(flag) printf(" ");
    70             printf("%d",i);
    71             flag=true;
    72         }
    73     }
    74     printf("
    ");
    75     return 0;
    76 }

     两个dfs分开的形式,练习一下。读入挂将*10变为(x<<3)+(x<<1),变为188ms了。

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 #include<cstdlib>
     5 #include<cmath>
     6 #include<iostream>
     7 #define inf 0x3f3f3f3f
     8 using namespace std;
     9 typedef long long ll;
    10 const int maxn=1e5+3;
    11 int head[maxn],tot,n;
    12 struct edge{
    13     int to;
    14     int nxt;
    15     int w;
    16 }e[maxn<<1];
    17 
    18 void add_edge(int u,int v,int w){
    19     e[tot].to=v;
    20     e[tot].w=w;
    21     e[tot].nxt=head[u];
    22     head[u]=tot++;
    23 }
    24 int dp[maxn<<2],cnt[maxn];
    25 
    26 void dfs(int u,int fa){
    27     cnt[u]=1;
    28     for(int i=head[u];i!=-1;i=e[i].nxt){
    29         int v=e[i].to;
    30         if(v==fa) continue;
    31         dfs(v,u);
    32         cnt[u]+=cnt[v];
    33     }
    34 }
    35 
    36 void dfs2(int u,int fa){    
    37     dp[u]=n-cnt[u];
    38     for(int i=head[u];i!=-1;i=e[i].nxt){
    39         int v=e[i].to;
    40         if(v==fa) continue;
    41         dfs2(v,u);
    42         dp[u]=max(dp[u],cnt[v]);
    43     }
    44 }
    45 
    46 inline int read(){
    47     char k=0;char ls;ls=getchar();for(;ls<'0'||ls>'9';k=ls,ls=getchar());
    48     int x=0;for(;ls>='0'&&ls<='9';ls=getchar())x=(x<<3)+(x<<1)+ls-'0';
    49     if(k=='-')x=0-x;return x;
    50 }
    51 int main(){
    52     //ios::sync_with_stdio(0);
    53     //cin.tie(0);
    54     //cout.tie(0);
    55     n=read();
    56     memset(head,-1,sizeof head);
    57     tot=0;
    58     int a,b;
    59     for(int i=0;i<n-1;i++){
    60         //scanf("%d%d",&a,&b);
    61         //cin>>a>>b;
    62         a=read();
    63         b=read();
    64         add_edge(a,b,1);
    65         add_edge(b,a,1);
    66     }
    67     dfs(1,-1);
    68     dfs2(1,-1);
    69     int ans=inf;
    70     for(int i=1;i<=n;i++){
    71         ans=min(ans,dp[i]);
    72     }
    73     bool flag=false;
    74     for(int i=1;i<=n;i++){
    75         if(dp[i]==ans){
    76             if(flag) printf(" ");
    77             printf("%d",i);
    78             flag=true;
    79         }
    80     }
    81     printf("
    ");
    82     return 0;
    83 }
  • 相关阅读:
    SDN第二次作业
    事后诸葛亮
    SDN第一次上机作业
    个人作业——软件产品案例分析
    SDN第一次作业
    Alpha冲刺总结报告
    Alpha冲刺Day10
    Alpha冲刺Day9
    Alpha冲刺Day8
    Alpha冲刺Day7
  • 原文地址:https://www.cnblogs.com/elpsycongroo/p/7419509.html
Copyright © 2020-2023  润新知