noip2018 赛道修建

洛谷P5021

http://210.33.19.103/contest/1050/problem/3

http://210.33.19.103/contest/1054/problem/3

multiset版本(TLE)

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<vector>
 5 #include<set>
 6 using namespace std;
 7 #define fi first
 8 #define se second
 9 #define mp make_pair
10 #define pb push_back
11 typedef long long ll;
12 typedef unsigned long long ull;
13 typedef pair<int,int> pii;
14 #define int ll
15 struct E
16 {
17     int to,nxt,d;
18 }e[200100];
19 int f1[100100],ne;
20 int n,m;
21 int d1[100100],d2[100100];//d1表示最大产生答案,d2表示剩下的到根最长路径
22 int x;
23 multiset<int> s;
24 multiset<int>::iterator i1;
25 void dfs(int u,int fa)
26 {
27     d1[u]=d2[u]=0;
28     int v;
29     for(int k=f1[u];k;k=e[k].nxt)
30     {
31         v=e[k].to;
32         if(v!=fa)
33         {
34             dfs(v,u);
35             d1[u]+=d1[v];
36         }
37     }
38     int num=0,t1,max1=0;
39     s.clear();
40     for(int k=f1[u];k;k=e[k].nxt)
41         if(e[k].to!=fa)
42         {
43             t1=d2[e[k].to]+e[k].d;
44             if(t1>=x)    {++num;}
45             else    s.insert(t1);
46         }
47     while(!s.empty())
48     {
49         i1=s.begin();
50         t1=*i1;s.erase(i1);
51         i1=s.lower_bound(x-t1);
52         if(i1==s.end())    {max1=max(max1,t1);continue;}
53         s.erase(i1);
54         ++num;
55     }
56     d1[u]+=num;
57     d2[u]=max1;
58     if(!s.empty())    d2[u]=max(d2[u],*s.rbegin());
59 }
60 bool judge()
61 {
62     dfs(1,0);
63     /*
64     printf("1t%d\n",x);
65     for(int i=1;i<=n;++i)
66         printf("%d ",d1[i]);
67     puts("");
68     */
69     return d1[1]>=m;
70 }
71 signed main()
72 {
73     int i,x,y,z;
74     scanf("%lld%lld",&n,&m);
75     for(i=1;i<n;++i)
76     {
77         scanf("%lld%lld%lld",&x,&y,&z);
78         e[++ne].to=y;e[ne].nxt=f1[x];f1[x]=ne;e[ne].d=z;
79         e[++ne].to=x;e[ne].nxt=f1[y];f1[y]=ne;e[ne].d=z;
80     }
81     int l=1,r=500000000,mid;
82     while(l!=r)
83     {
84         mid=l+((r-l)>>1);
85         if(::x=mid+1,judge())    l=mid+1;
86         else    r=mid;
87     }
88     printf("%lld\n",l);
89     return 0;
90 }
View Code

可AC版本

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<vector>
 5 #include<set>
 6 using namespace std;
 7 #define fi first
 8 #define se second
 9 #define mp make_pair
10 #define pb push_back
11 typedef long long ll;
12 typedef unsigned long long ull;
13 typedef pair<int,int> pii;
14 struct E
15 {
16     int to,nxt,d;
17 }e[200100];
18 int f1[100100],ne;
19 int n,m;
20 int d1[100100],d2[100100];//d1表示最大产生答案,d2表示剩下的到根最长路径
21 int x;
22 int s[100100];
23 int fa1[100100];
24 int find(int x){return x==fa1[x]?x:fa1[x]=find(fa1[x]);}
25 void dfs(int u,int fa)
26 {
27     d1[u]=d2[u]=0;
28     int v;
29     for(int k=f1[u];k;k=e[k].nxt)
30     {
31         v=e[k].to;
32         if(v!=fa)
33         {
34             dfs(v,u);
35             d1[u]+=d1[v];
36         }
37     }
38     int num=0,t1,t2,max1=0,i;
39     s[0]=0;
40     for(int k=f1[u];k;k=e[k].nxt)
41         if(e[k].to!=fa)
42         {
43             t1=d2[e[k].to]+e[k].d;
44             if(t1>=x)    ++num;
45             else    s[++s[0]]=t1;
46         }
47     sort(s+1,s+s[0]+1);
48     for(i=1;i<=s[0]+1;++i)    fa1[i]=i;
49     while(1)
50     {
51         t1=find(1);
52         if(t1>s[0])    break;
53         fa1[t1]=find(t1+1);
54         t2=lower_bound(s+1,s+s[0]+1,x-s[t1])-s;
55         t2=find(t2);
56         if(t2>s[0])    {max1=max(max1,s[t1]);continue;}
57         fa1[t2]=find(t2+1);
58         ++num;
59     }
60     d1[u]+=num;
61     d2[u]=max1;
62     for(i=1;i<=s[0];++i)
63         if(fa1[i]==i)
64             d2[u]=max(d2[u],s[i]);
65 }
66 bool judge()
67 {
68     dfs(1,0);
69     return d1[1]>=m;
70 }
71 signed main()
72 {
73     int i,x,y,z;
74     scanf("%d%d",&n,&m);
75     for(i=1;i<n;++i)
76     {
77         scanf("%d%d%d",&x,&y,&z);
78         e[++ne].to=y;e[ne].nxt=f1[x];f1[x]=ne;e[ne].d=z;
79         e[++ne].to=x;e[ne].nxt=f1[y];f1[y]=ne;e[ne].d=z;
80     }
81     int l=1,r=500000000,mid;
82     while(l!=r)
83     {
84         mid=l+((r-l)>>1);
85         if(::x=mid+1,judge())    l=mid+1;
86         else    r=mid;
87     }
88     printf("%d\n",l);
89     return 0;
90 }
View Code

 

posted @ 2018-11-17 10:33  hehe_54321  阅读(257)  评论(0编辑  收藏  举报
AmazingCounters.com