考場上寫了一大坨樹形dp,寫的時候就感覺我這不是跟求樹的最長鏈寫的一毛一樣
然後考後看題解,果然是k個ren所連成的子樹的最長鏈的一半
可以利用反證法證明,如果在長度為d的最長鏈的中間放乙個中心,如果有另外乙個點到這個點的長度》(d+1)/2,那麼這個點到對面的那個點的長度大於d,所以不存在這樣乙個點。
#include#define maxl 100010
using namespace std;
int n,cnt,k,ans;
int a[maxl],ehead[maxl],dis[maxl];
struct ed
e[maxl*2];
bool in[maxl],vis[maxl];
inline void add(int u,int v)
inline void prework()
for(int i=1;i<=k;i++) }
inline void dfs(int u) }}
inline void mainwork()
for(int i=1;i<=n;i++)
vis[i]=false,dis[i]=0;
dfs(a[1]);
int u=a[1];
for(int i=1;i<=k;i++)
if(dis[a[i]]>dis[u])
u=a[i];
for(int i=1;i<=n;i++)
vis[i]=false,dis[i]=0;
dfs(u);
int v=u;
for(int i=1;i<=k;i++)
if(dis[a[i]]>dis[v])
v=a[i];
ans=(dis[v]+1)/2;
}inline void print()
int main()
return 0;
}
樹形dp版本,又臭又長:
#include#define maxl 100010
using namespace std;
const int inf=2e9;
int n,k,cnt,ans;
int ehead[maxl];
int f[maxl],mxfa[maxl],mxs[maxl],secmxs[maxl];
bool mxflag[maxl],secmxflag[maxl],faflag[maxl];
struct ed
e[maxl<<1];
bool in[maxl];
inline void add(int u,int v)
inline void prework()
for(int i=1;i<=k;i++)
} inline void gets(int u,int fa)
else if(tmp>secmxs[u])
secmxs[u]=tmp,secmxflag[u]=true;}}
} }
inline void getf(int u,int fa)
}else
}if(faflag[fa])
}for(int i=ehead[u];i;i=e[i].nxt)
if(faflag[u])
f[u]=mxfa[u];
if(mxs[u])
f[u]=max(f[u],mxs[u]);}
inline void mainwork()
gets(1,0);
mxfa[1]=0;
getf(1,0);
ans=inf;
for(int i=1;i<=n;i++)
ans=min(ans,f[i]);}
inline void print()
int main()
return 0;
}
2019牛客多校第四場 D triples I
對於二進位制每一位上的1進行考慮,2 0 3 1 2 1 3 2 2 2 3 1 2 3 3 2 那麼我們可以想到把a轉化為二進位制,然後他 3 1的位數有cnt1個,3 2的位數有cnt2個。我們可以想到每個數字最多由2個數字組成,下面給出證明。那麼 sum a 3,如果sum 0,那麼直接乙個數...
2019牛客多校第四場A K
a.給你一張n個點n 1條邊的圖,和k個關鍵點。求乙個點到所有關鍵點距離最大值的最小為多少。乍一看像是對答案二分,但是考慮兩個相距最遠的關鍵點,假設他們的距離為d,那麼答案肯定為 d 1 2 如果有一點到中心點的距離超過了 d 1 2 那麼這個點會成為最遠關鍵點對中的乙個。矛盾。所以題目就變成了如何...
2019牛客多校第四場A meeting 思維
乙個樹上有若干點上有人,找出乙個集合點,使得所有人都到達這個點的時間最短 無碰撞 就是找樹的直徑,找直徑的時候記得要找有人的點 include include includeusing namespace std define pb push back define f first define s...