Loj2977 chocolate (Steiner tree+randomization)

When considering less colors, the first question is Steiner tree

The second question is to consider two points. Each time, the weight of each grid is given as 1000+[a [i]>m], that is, on the basis of the minimum number, try to choose the one less than or equal to m

However, there are too many colors to do directly, but each color can be mapped to within 5. In this case, the correct rate of doing one time is the probability that the five colors as the answer are mapped to 1~5, that is, $ frac {5!} {5 ^ 5}=0.0384 $, and the correct rate of doing 233 times is $99.989 % $

 one #include<bits/stdc++.h> two #include<tr1/unordered_map> three  #define CLR(a,x) memset(a,x,sizeof(a)) four  #define MP make_pair five  #define fi first six  #define se second seven  using  namespace std; eight typedef long  long ll; nine typedef unsigned long  long ull; ten typedef long  double ld; eleven typedef pair< int , int > pa; twelve  const  int maxn= two hundred and fifty ,maxp= fifty ; thirteen 
 fourteen  inline ll rd(){ fifteen ll x= zero ; char c=getchar(); int neg= one ; sixteen      while (c< ' zero ' ||c> ' nine ' ){ if (c== ' - ' ) neg=- one ; c= getchar();} seventeen      while (c>= ' zero ' &&c<= ' nine ' ) x=x* ten +c- ' zero ' ,c= getchar(); eighteen      return x* neg; nineteen  } twenty 
 twenty-one  int step[ four ][ two ]={{ zero , one },{ zero ,- one },{ one , zero },{- one , zero }}; twenty-two  int id[maxn][maxn],pct,pos[maxn][ two ]; twenty-three  int N,M,S,K; twenty-four  int f[maxn][maxp],c[maxn],a[maxn],val[maxn]; twenty-five  int hsh[maxn],C; twenty-six 
 twenty-seven queue< int > q; twenty-eight  bool flag[maxn]; twenty-nine inline void spfa( int s){ thirty      for ( int i= one ; i<=pct; i++) if (c[i]!=- one ) flag[i]= one ,q.push(i); thirty-one     
 thirty-two      while (! q.empty()){ thirty-three          int p= q.front(); q.pop(); thirty-four flag[p]= zero ; thirty-five          int x=pos[p][ zero ],y=pos[p][ one ]; thirty-six          for ( int j= zero ; j< four ; j++ ){ thirty-seven              int nx=x+step[j][ zero ],ny=y+step[j][ one ]; thirty-eight              if (nx< one ||ny< one ||nx>N||ny>M||c[id[nx][ny]]==- one ) continue ; thirty-nine              int ni= id[nx][ny]; forty              if (f[ni][s]>f[p][s]+ val[ni]){ forty-one f[ni][s]=f[p][s]+ val[ni]; forty-two                  if (!flag[ni]) q.push(ni),flag[ni]= one ; forty-three  } forty-four  } forty-five  } forty-six  } forty-seven 
 forty-eight inline int solve(){ forty-nine CLR(f, sixty-three ); fifty      for ( int i= one ; i<=pct; i++) if (c[i]!=- one ) f[i][ one <<hsh[c[i]]]= val[i]; fifty-one      for ( int s= one ; s<( one <<K); s++ ){ fifty-two          for ( int i= one ; i<=pct; i++ ){ fifty-three              if (c[i]==- one ) continue ; fifty-four              for ( int ss=(s- one )&s; ss; ss=(ss- one )& s){ fifty-five f[i][s]=min(f[i][s],f[i][ss]+f[i][s^ss]- val[i]); fifty-six  } fifty-seven  } fifty-eight  spfa(s); fifty-nine  } sixty      int ans= 1e9; sixty-one      for ( int i= one ; i<=pct; i++) ans=min(ans,f[i][( one <<K)- one ]); sixty-two      return ans; sixty-three  } sixty-four 
 sixty-five  int main(){ sixty-six      // freopen("","r",stdin);
 sixty-seven srand( nineteen million two hundred and sixty thousand eight hundred and seventeen ); sixty-eight      for ( int T=rd(); T; T-- ){ sixty-nine pct= zero ,C= zero ; seventy N=rd(),M=rd(),K= rd(); seventy-one          for ( int i= one ; i<=N; i++ ){ seventy-two              for ( int j= one ; j<=M; j++) id[i][j]=++pct,pos[pct][ zero ]=i,pos[pct][ one ]= j; seventy-three  } seventy-four          for ( int i= one ; i<=N; i++) for ( int j= one ; j<=M; j++) c[id[i][j]]=rd(),C= max(C,c[id[i][j]]); seventy-five          for ( int i= one ; i<=N; i++) for ( int j= one ; j<=M; j++) a[id[i][j]]= rd(); seventy-six          int ans1=1e9,ans2= 1e9; seventy-seven          for ( int t= one ; t<= two hundred and thirty-three ; t++ ){ seventy-eight              for ( int i= one ; i<=C; i++) hsh[i]=rand()% K; seventy-nine              int l= zero ,r=1e6,a1=1e9,a2= 1e9; eighty              while (l<= r){ eighty-one                  int m=(l+r)>> one ; eighty-two                  for ( int i= one ; i<=pct; i++) val[i]=(c[i]==- one ? 1e8: one thousand +(a[i]> m)); eighty-three                  int re= solve(); eighty-four                  if (re>=1e8) break ; eighty-five a1=re/ one thousand ; eighty-six                  int x=a1-(re-a1* one thousand ); eighty-seven                  if (x>=(a1+ one )/ two ) a2=m,r=m- one ; eighty-eight                  else l=m+ one ; eighty-nine  } ninety              if (a1<ans1||(ans1==a1&&a2<=ans2)) ans1=a1,ans2= a2; ninety-one  } ninety-two         
 ninety-three printf( " %d %d\n " ,ans1==1e9?- one :ans1,ans1==1e9?- one :ans2); ninety-four  } ninety-five      return  zero ; ninety-six }

 

posted @ 2019-03-28 11:00   Ressed   Reading( two hundred and forty-eight Comments( zero edit   Collection   report