Loj2977 chocolate (Steiner tree+randomization)
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 }