題目描述的實際是一顆二叉樹,對於每個結點,要麼滿叉,要麼無叉。
對於一種無解的簡單情況,我們搜一遍樹找到最淺的葉子結點1和最深的葉子結點2,如果dep[1]所以現在所有的葉子結點的深度要麼是dep[1]和dep[2].
我們可以把所有結點用node[x]標記狀態。
node[x]=0表示x的子樹下所有葉子結點深度都是dep[2]。
node[x]=1表示x的子樹下一部分葉子結點深度是dep[1],一部分是dep[2]。
node[x]=2表示x的子樹下所有葉子結點深度都是dep[1]。
現在有,假設x的兒子結點的node值都是1,則一定無解。證明是顯然的。
假設x的左兒子結點node值大於右兒子結點的node值,則ans+1,表示需要操作一次。證明也是顯然的。
另外node值可以通過一次樹形dp得到,所以總複雜度為o(n).
# include # includeview code# include
# include
# include
# include
# include
# include
# include
# include
# include
using
namespace
std;
# define lowbit(x) ((x)&(-x))
# define pi acos(-1.0
)# define eps 1e-8
# define mod
1000000007
# define inf
1000000000
# define mem(a,b) memset(a,b,
sizeof
(a))
# define for(i,a,n)
for(int i=a; i<=n; ++i)
# define fo(i,a,n)
for(int i=a; ii)
# define bug puts("h
");# define lch p
<<1
,l,mid
# define rch p
<<1|1,mid+1
,r# define mp make_pair
# define pb push_back
typedef pair
pii;
typedef vector
vi;# pragma comment(linker,
"/stack:1024000000,1024000000")
typedef
long
long
ll;int
scan()
void out(int
a)
if(a>=10) out(a/10
); putchar(a%10+'0'
);}const
int n=100005;//
code begin...
int pos, mi=inf, ma=0, node[n*10], dep[n*10], n, ans, son[n][2
];void dfs1(intx)}
bool dfs2(int
x)
else
}return1;
}int
main ()
dfs1(1);
if (mi1||dfs2(1)==0) puts("-1"
);
else printf("
%d\n
",ans);
return0;
}
BZOJ 1040 騎士(樹形DP)
題意 給出乙個圖,只有乙個環。每個點有乙個權值。選出一些點兩兩不相鄰,使得權值最大?思路 1 找到環。dfs,標記訪問,下乙個節點不是父節點但是已被訪問則這條邊就是環上的兩個點。標記這個邊是我們找到的環邊,並將這兩個點的中乙個設定為root,另乙個我們設為node 2 由於root和node不能同時...
bzoj1487 無歸島 樹形dp
對於題目中的一句話 對於同乙個島上的任意兩個生物,他們有且僅有乙個公共朋友,即對同一島上的任意兩個生物a和b有且僅有乙個生物c既是a的朋友也是b的朋友。我個人以為他是說這乙個島上的點構成乙個環,否則我看不懂樣例中的圖是怎麼符合題意的。果然我是語體教 那麼這句話是說有x個環,這x個環又構成乙個環。這道...
秘密襲擊 BZOJ5250 樹形DP
分析 聽說正解是fft 線段樹合併,然而我並不會.我們來思考其他的方法。我們要求的是連通塊第k大的和 對於某乙個連通塊,對答案的貢獻 val rank.k 我們不好直接算出每個連通塊的rank.k是多少 但我們可以列舉乙個limit for 1 w val rank.k lim的連通塊的個數 就等於...