2 条题解

  • 0
    @ 2025-10-8 16:51:43
    //Code By zzh 2023.10.6
    #include<bits/stdc++.h>
    using namespace std;
    const int N=310;
    const int INF=0x3f3f3f3f;
    struct edge{
        int x,y,pre;
    }a[N*2];
    int alen,last[N];
    void ins(int x,int y)
    {
        a[++alen]={x,y,last[x]};
        last[x]=alen;
    }
    int n,p;
    int siz[N],dep[N];//siz[i]:以i号点为根节点的子树的大小 dep[i]:i号点的深度
    void init(int x,int fa)//预处理出每个点的深度以及以这个点为根节点的子树的大小
    {
        for(int k=last[x];k;k=a[k].pre)
        {
            int y=a[k].y;
            if(y==fa) continue;//防止前往上一层
            dep[y]=dep[x]+1;
            init(y,x);
            siz[x]+=siz[y];
        }
    }
    int ans=INF,max_dep=0;//max_dep:整棵树的深度
    bool v[N];//标记每个点是否被删除
    void dfs_1(int x,int fa,int op)
    {
        v[x]=op;
        for(int k=last[x];k;k=a[k].pre)
        {
            int y=a[k].y;
            if(y==fa) continue;
            dfs_1(a[k].y,x,op);
        }
    }
    //dfs枚举每一层删除哪一条边
    void dfs(int d,int sum)//sum:还剩多少个点
    {
        ans=min(ans,sum);
        if(d==max_dep) return;//到达最深层
        for(int x=1;x<=n;x++)
        {
            if(dep[x]!=d||v[x]) continue;
            for(int k=last[x];k;k=a[k].pre)
            {
                int y=a[k].y;
                if(dep[y]!=d+1||v[y]) continue;
                dfs_1(y,x,1);//将x到y这条边删除,也就是将以y为根的子树全部删除
                dfs(d+1,sum-siz[y]);//减去以y为根的子树的大小
                dfs_1(y,x,0);//回溯
            }
        }
    }
    int main()
    {
        scanf("%d%d",&n,&p);
        for(int i=1;i<=p;i++)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            ins(x,y),ins(y,x);
        }
        for(int i=1;i<=n;i++) siz[i]=1;
        dep[1]=1;init(1,-1);
        for(int i=1;i<=n;i++) max_dep=max(max_dep,dep[i]);
        dfs(1,siz[1]);
        printf("%d\n",ans);
        return 0;
    }
    
    • 0
      @ 2025-10-8 16:51:31
      //Code By zzh 2023.10.6
      #include<bits/stdc++.h>
      using namespace std;
      const int N=310;
      const int INF=0x3f3f3f3f;
      struct edge{
      	int x,y,pre;
      }a[N*2];
      int alen,last[N];
      void ins(int x,int y)
      {
      	a[++alen]={x,y,last[x]};
      	last[x]=alen;
      }
      int n,p;
      int siz[N],dep[N];//siz[i]:以i号点为根节点的子树的大小 dep[i]:i号点的深度
      void init(int x,int fa)//预处理出每个点的深度以及以这个点为根节点的子树的大小
      {
      	for(int k=last[x];k;k=a[k].pre)
      	{
      		int y=a[k].y;
      		if(y==fa) continue;//防止前往上一层
      		dep[y]=dep[x]+1;
      		init(y,x);
      		siz[x]+=siz[y];
      	}
      }
      int ans=INF,max_dep=0;//max_dep:整棵树的深度
      bool v[N];//标记每个点是否被删除
      void dfs_1(int x,int fa,int op)
      {
      	v[x]=op;
      	for(int k=last[x];k;k=a[k].pre)
      	{
      		int y=a[k].y;
      		if(y==fa) continue;
      		dfs_1(a[k].y,x,op);
      	}
      }
      //dfs枚举每一层删除哪一条边
      void dfs(int d,int sum)//sum:还剩多少个点
      {
      	ans=min(ans,sum);
      	if(d==max_dep) return;//到达最深层
      	for(int x=1;x<=n;x++)
      	{
      		if(dep[x]!=d||v[x]) continue;
      		for(int k=last[x];k;k=a[k].pre)
      		{
      			int y=a[k].y;
      			if(dep[y]!=d+1||v[y]) continue;
      			dfs_1(y,x,1);//将x到y这条边删除,也就是将以y为根的子树全部删除
      			dfs(d+1,sum-siz[y]);//减去以y为根的子树的大小
      			dfs_1(y,x,0);//回溯
      		}
      	}
      }
      int main()
      {
      	scanf("%d%d",&n,&p);
      	for(int i=1;i<=p;i++)
      	{
      		int x,y;
      		scanf("%d%d",&x,&y);
      		ins(x,y),ins(y,x);
      	}
      	for(int i=1;i<=n;i++) siz[i]=1;
      	dep[1]=1;init(1,-1);
      	for(int i=1;i<=n;i++) max_dep=max(max_dep,dep[i]);
      	dfs(1,siz[1]);
      	printf("%d\n",ans);
      	return 0;
      }
      • 1

      信息

      ID
      289
      时间
      1000ms
      内存
      128MiB
      难度
      9
      标签
      递交数
      8
      已通过
      7
      上传者