zoukankan      html  css  js  c++  java
  • CF1029E Tree with Small Distances

    LXIII.CF1029E Tree with Small Distances

    我们发现,如果一个点与\(1\)连了边,那么它的儿子们以及它的父亲都会变成合法的。

    因此我们可以设\(f[i][0/1/2]\)表示:\(i\)的某个儿子中有边/\(i\)自己有边/\(i\)的父亲应该有边的最小值。

    转移:

    \(0\):可以从儿子的\(0\)\(1\)转移,且儿子中至少有一个为\(1\)(即,找到\(1\)\(0\)差最小的那个换成\(1\)

    \(1\)\(0/1/2\)皆可,取\(\min\)即可。

    \(2\)\(0/1\)\(\min\)

    复杂度\(O(n)\)

    最后说一下答案,应该是\(1\)的所有儿子的\((f[x][1]-1)\)的和,因为\(1\)的所有儿子都相当于连了一条免费的边。

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    int n,head[1001000],cnt,f[1001000][3],res;//0:have a son;1:itself;2:have a father 
    struct node{
    	int to,next;
    }edge[2001000];
    void ae(int u,int v){
    	edge[cnt].next=head[u],edge[cnt].to=v,head[u]=cnt++;
    }
    void dfs(int x,int fa){
    	int mn=0x3f3f3f3f;
    	f[x][1]=1;
    	for(int i=head[x],y;i!=-1;i=edge[i].next){
    		if((y=edge[i].to)==fa)continue;
    		dfs(y,x);
    		f[x][0]+=min(f[y][0],f[y][1]),mn=min(mn,f[y][1]-f[y][0]);
    		f[x][1]+=min(f[y][0],min(f[y][1],f[y][2]));
    		f[x][2]+=min(f[y][0],f[y][1]);
    		if(x==1)res+=f[y][1]-1;
    	}
    	f[x][0]+=max(mn,0);
    }
    int main(){
    	scanf("%d",&n),memset(head,-1,sizeof(head));
    	for(int i=1,x,y;i<n;i++)scanf("%d%d",&x,&y),ae(x,y),ae(y,x);
    	dfs(1,0);
    	printf("%d\n",res);
    	return 0;
    } 
    

  • 相关阅读:
    苹果输入手机号变用户的名字
    iOS 关于UITableView的黑科技
    iOS 详解NSObject协议
    iOS 用xib自定义View
    iOS 关于定位你该注意的那些事
    iOS 内存泄漏
    Swift应用案例 2.闭包入门到精通
    Swift应用案例 1.无限轮播
    多库共存-冲突问题
    多库共存-冲突问题
  • 原文地址:https://www.cnblogs.com/Troverld/p/14597534.html
Copyright © 2011-2022 走看看