NC20261. [SCOI2008]城堡CASTLE
描述
输入描述
输入第一行为三个正整数n, m, k。第二行包含n个整数r0,r1,…,rn-1。第三行包含n个整数d0,d1,…,dn-1。第四行包含m个各不相同的0~n-1之间的整数,分别为m个城堡所在的城市编号。
输出描述
输出仅一行,包含一个整数,即max{dist(c)}的最小值。
示例1
输入:
5 0 1 1 2 3 4 0 1 1 1 1 1
输出:
2
示例2
输入:
3 1 1 1 2 0 1 2 3 2
输出:
1
示例3
输入:
2 1 1 0 1 1 1 1
输出:
0
示例4
输入:
10 3 3 0 2 0 0 2 2 8 3 8 7 10 9 1 8 1 3 7 2 8 1 3 4 6
输出:
3
示例5
输入:
2 0 1 1 0 5 10
输出:
5
C++(g++ 7.5.0) 解法, 执行用时: 4ms, 内存消耗: 396K, 提交时间: 2022-10-24 17:27:23
#include<cstdio> #include<cstring> #define Min(a,b) ((a)>(b)?(b):(a)) using namespace std; const int INF=0x7ffffff; int n,m,k,x,i,j,l; int L,R,mid; int r[55],d[55],h[55]; int dt[55][55]; bool judge(int x) { int temp=k,tot=m,i,j,t,u,v; int c[55],p[55]; for (i=0;i<n;i++)c[i]=h[i]; for (i=0;i<n;i++) if (!c[i]) { t=INF; for (j=0;j<n;j++) if (c[j]==1)t=Min(t,dt[i][j]); if (t<=x)c[i]=2,tot++; } if (tot==n)return 1; while (temp--) { memset(p,0,sizeof(p)); for (i=0;i<n;i++) if (!c[i]) { for (j=0;j<n;j++) if (c[j]!=1&&dt[i][j]<=x)p[j]++; } u=0; for (i=0;i<n;i++) if (c[i]!=1&&p[i]>=u)u=p[i],v=i; if (!c[v])tot++;c[v]=1; for (i=0;i<n;i++) if (!c[i]) { t=INF; for (j=0;j<n;j++) if (c[j]==1)t=Min(t,dt[i][j]); if (t<=x)c[i]=2,tot++; } if (tot==n)return 1; } return 0; } int main() { scanf("%d%d%d",&n,&m,&k); for (i=0;i<n;i++) for (j=0;j<n;j++) dt[i][j]=(i==j)?0:INF; for (i=0;i<n;i++)scanf("%d",&r[i]); for (i=0;i<n;i++) { scanf("%d",&d[i]);R+=d[i]; dt[i][r[i]]=dt[r[i]][i]=Min(dt[i][r[i]],d[i]); } for (i=1;i<=m;i++) { scanf("%d",&x); h[x]=1; } for (l=0;l<n;l++) for (i=0;i<n;i++) for (j=0;j<n;j++) if (i!=j&&i!=l&&j!=l) if (dt[i][l]+dt[l][j]<dt[i][j]) dt[i][j]=dt[i][l]+dt[l][j]; L=0; while (L<=R) { mid=(L+R)>>1; if (judge(mid))R=mid-1; else L=mid+1; } printf("%d\n",L); }
C++11(clang++ 3.9) 解法, 执行用时: 28ms, 内存消耗: 376K, 提交时间: 2019-12-15 08:28:35
#include<bits/stdc++.h> #define N 61 #define fo(i,a,b) for(int i=a;i<=b;i++) using namespace std; int n,m,k,g[N],h[N],b[N],cnt,dis[N][N],a[N],d; bool f[N]; int solve() { memcpy(h,g,sizeof(g)); fo(i,1,k)fo(j,1,n)h[j]=min(h[j],dis[b[i]][j]); int ans=0; fo(i,1,n)ans=max(ans,h[i]); return ans; } int main() { srand(time(0)); scanf("%d%d%d",&n,&m,&k); fo(i,1,n)scanf("%d",&a[i]),a[i]++; memset(g,0x7f,sizeof(g)); memset(dis,0x3f,sizeof(dis)); fo(i,1,n)dis[i][i]=0,scanf("%d",&d),dis[i][a[i]]=dis[a[i]][i]=min(dis[i][a[i]],d); fo(l,1,n)fo(i,1,n)fo(j,1,n)dis[i][j]=min(dis[i][j],dis[i][l]+dis[l][j]); fo(i,1,m)scanf("%d",&d),f[++d]=1; fo(i,1,n) if(!f[i])b[++cnt]=i; else fo(j,1,n)g[j]=min(g[j],dis[i][j]); random_shuffle(b+1,b+cnt+1); int T=5,pre,ans=solve(); while(T--) { random_shuffle(b+1,b+cnt+1); ans=min(ans,solve()); int G=20; while (G--) { fo(i,k+1,cnt) fo(j,1,k) { swap(b[i],b[j]); pre=ans,ans=solve(); if(ans>pre)ans=pre,swap(b[i],b[j]); } } } printf("%d",ans); }