【点分治】【哈希表】bzoj2599 [IOI2011]Race
给nlog2n随便过的跪了,不得已弄了个哈希表伪装成nlogn(当然随便卡,好孩子不要学)……
不过为啥哈希表的大小开小点就RE啊……?必须得超过数据范围一大截才行……谜
#include<cstdio> #include<algorithm> #include<cstring> using namespace std; int f,c; inline void R(int &x){ c=0;f=1; for(;c<'0'||c>'9';c=getchar())if(c=='-')f=-1; for(x=0;c>='0'&&c<='9';c=getchar())(x*=10)+=(c-'0'); x*=f; } #define INF 2147483647 #define MAXN 200001 #define MOD 200003 #define MAXN2 290003 typedef pair<int,int> Point; struct HashTable { Point v[MAXN2]; int en,first[MOD],next[MAXN2]; HashTable(){en=0;memset(first,-1,sizeof(first));} void insert(const Point &V) { int U=(int)(V.first%MOD); for(int i=first[U];i!=-1;i=next[i]) if(v[i].first==V.first) {v[i].second=min(v[i].second,V.second); return;} v[en]=V; next[en]=first[U]; first[U]=en++; } }T; int n,K,ans=INF,last; int v[MAXN<<1],w[MAXN<<1],first[MAXN],next[MAXN<<1],en; void AddEdge(const int &U,const int &V,const int &W) {v[++en]=V; w[en]=W; next[en]=first[U]; first[U]=en;} bool centroid[MAXN]; int size[MAXN]; int calc_sizes(int U,int Fa) { int res=1; for(int i=first[U];i;i=next[i]) if(v[i]!=Fa&&(!centroid[v[i]])) res+=calc_sizes(v[i],U); return size[U]=res; } Point calc_centroid(int U,int Fa,int nn) { Point res=make_pair(INF,-1); int sum=1,maxv=0; for(int i=first[U];i;i=next[i]) if(v[i]!=Fa&&(!centroid[v[i]])) { res=min(res,calc_centroid(v[i],U,nn)); maxv=max(maxv,size[v[i]]); sum+=size[v[i]]; } maxv=max(maxv,nn-sum); res=min(res,make_pair(maxv,U)); return res; } Point dis[MAXN]; int En; void calc_dis(int U,int Fa,int d,int cnt) { dis[En++]=make_pair(d,cnt); for(int i=first[U];i;i=next[i]) if(v[i]!=Fa&&(!centroid[v[i]])) calc_dis(v[i],U,d+w[i],cnt+1); } int calc_pairs() { int res=0; for(int i=last;i<En;++i) { int U=(int)((K-dis[i].first)%MOD); for(int j=T.first[U];j!=-1;j=T.next[j]) if(T.v[j].first==K-dis[i].first) { ans=min(T.v[j].second+dis[i].second,ans); break; } } for(int i=last;i<En;++i) T.insert(dis[i]); } void solve(int U) { calc_sizes(U,-1); int s=calc_centroid(U,-1,size[U]).second; centroid[s]=1; for(int i=first[s];i;i=next[i]) if(!centroid[v[i]]) solve(v[i]); En=0; dis[En]=make_pair(0,0); T.insert(dis[En++]); for(int i=first[s];i;i=next[i]) if(!centroid[v[i]]) { last=En; calc_dis(v[i],s,w[i],1); calc_pairs(); } for(int i=0;i<En;++i) T.first[dis[i].first%MOD]=-1; T.en=0; centroid[s]=0; } int main() { int a,b,c; R(n); R(K); if(!K) {puts("0"); return 0;} for(int i=1;i<n;++i) { R(a); R(b); R(c); AddEdge(a,b,c); AddEdge(b,a,c); } solve(1); printf("%d\n",ans==INF ? -1 : ans); return 0; }
——The Solution By AutSky_JadeK From UESTC
转载请注明出处:http://www.cnblogs.com/autsky-jadek/