BZOJ2067 [Poi2004]SZN

来源:互联网 发布:结伴编程 编辑:程序博客网 时间:2024/05/16 00:58

第一问可以dp,第二问可以二分答案,然后再dp一遍判断

dp的时候记录最少用多少路径以及连着父亲的路径多长即可

把所有儿子按长度排序后尽量合并

复杂度n log^2 n

数据比较水,所以瞎几把合并一下就可以过了

#include<iostream>#include<cstring>#include<ctime>#include<cmath>#include<algorithm>#include<iomanip>#include<cstdlib>#include<cstdio>#include<map>#include<bitset>#include<set>#include<stack>#include<vector>#include<queue>using namespace std;#define MAXN 10010#define MAXM 1010#define ll long long#define eps 1e-8#define MOD 1000000007#define INF 1000000000struct vec{int to;int fro;};struct data{int c;int l;data(){}data(int _c,int _l){c=_c;l=_l;}friend bool operator <(data x,data y){return x.c!=y.c?x.c<y.c:x.l<y.l;}};vec mp[MAXN*2];int tai[MAXN],cnt;data f[MAXN];vector<int>ps[MAXN];int n;int ANS,ans;int lim;inline void be(int x,int y){mp[++cnt].to=y;mp[cnt].fro=tai[x];tai[x]=cnt;}inline void bde(int x,int y){be(x,y);be(y,x);}void dp(int x,int F){int i,y;bool flag=0;int mn=INF,mn1=INF,mn2=INF;f[x].c=0;f[x].l=0;ps[x].clear();for(i=tai[x];i;i=mp[i].fro){y=mp[i].to;if(y!=F){flag=1;dp(y,x);ps[x].push_back(f[y].l);f[x].c+=f[y].c;}}if(!flag){f[x].c=1;f[x].l=1;return ;}sort(ps[x].begin(),ps[x].end());int r=ps[x].size()-1;data tmp=f[x];for(i=1;i<r;i++){while(r>i&&ps[x][i]+ps[x][r]>lim){r--;}if(r>i){tmp.c--;r--;}}if(x!=1){tmp.c++;tmp.l=1;if(ps[x][0]+1<=lim){tmp.c--;tmp.l=ps[x][0]+1;}}for(i=0,r=ps[x].size()-1;i<r;i++){while(r>i&&ps[x][i]+ps[x][r]>lim){r--;}if(r>i){f[x].c--;ps[x][i]=-1;ps[x][r]=-1;r--;}}if(x!=1){f[x].c++;f[x].l=1;for(i=0;i<ps[x].size();i++){if(ps[x][i]!=-1&&ps[x][i]+1<=lim){f[x].c--;f[x].l=ps[x][i]+1;break;}}}f[x]=min(f[x],tmp);}int main(){int i,x,y;scanf("%d",&n);for(i=1;i<n;i++){scanf("%d%d",&x,&y);bde(x,y);}lim=n;dp(1,0);ANS=f[1].c;//*int l=1,r=n;while(l<=r){int mid=l+r>>1;lim=mid;dp(1,0);if(f[1].c==ANS){ans=mid;r=mid-1;}else{l=mid+1;}}//*/printf("%d %d\n",ANS,ans);return 0;}/*97 84 55 61 23 29 82 55 8*/


0 0
原创粉丝点击