【NOIP2012模拟8.7】找位置

    科技2024-12-29  26

    【NOIP2012模拟8.7】找位置

    Description

    Farmer John 想找一个最好的位置来建新农场,这样他每天可以少走些路。 FJ所在的区域,有N个城镇(1 <= N <= 10,000)。 城镇之间,有M(1 <= M <= 50,000)条双向路相连。 所有城镇都可以借助一些路相互连接。 FJ需要你的帮助来选择最合适建新农场的城镇。 K(1 <= K <= 5)个城镇中有超市,FJ每天都会去这些超市。 他计划每天从新农场出发,访问包含超市的K个城镇,然后返回新农场。 FJ可以按照任意的顺序访问这些超市。 FJ只会在N-K个城镇中,选择一个城镇来建新农场。因为其他城镇的房价,比较低一些。 如果他把农场建在最优的位置,而且尽可能明智的选择行走路线。 请帮FJ计算,他每天需要行走的路线长度。

    Input

    第1行:三个空格隔开的整数,N,M和K。 第2…1+K行:第i+1行包含一个整数,范围1…N,表示包含第i个超市的城镇。 每个超市在不同城镇。 第2+K…1+K+M行:每行包含三个空格隔开的整数,i,j(1 <= i,j <= N),和L(1 <= L <= 1000), 表示城镇i和城镇j之间存在一条长度为L的路。

    Output

    如果他把农场建在最优的位置,FJ每天需要行走的最短路线长度。

    Sample Input

    5 6 3 1 2 3 1 2 1 1 5 2 3 2 3 3 4 5 4 2 7 4 5 10

    Sample Output

    12

    Hint

    FJ在5号城镇建立农场。他每天的行走路线为5-1-2-3-2-1-5,路线长度为12

    题解

    水题 先预处理出每个超市到每个点的距离 因为超市只有5个,全排列枚举便利顺序,再枚举农场的位置

    code

    #include<cstdio> #include<cctype> #include<cstdlib> #include<cstring> #include<algorithm> #define R register using namespace std; const int N=10010,M=50010; int n,m,k,last,ans=0xfffffff,head[N],w[M*2],to[M*2],next[M*2],a[9],dis[6][N],vis[N],bj[N],b[9]; inline void read(R int &x){ x=0;char ch=getchar(); while(!isdigit(ch))ch=getchar(); while(isdigit(ch))x=(x<<1)+(x<<3)+(ch^48),ch=getchar(); } struct Node{int w,pos;}; struct node{ int cnt; Node q[M*2]; void push(Node x){ q[++cnt]=x; int y=cnt; while(y>1&&q[y].w<q[y>>1].w) q[0]=q[y],q[y]=q[y>>1],q[y>>1]=q[0],y>>=1; } Node top(){return q[1];} void pop(){ q[1]=q[cnt--]; int y=1,x; while((y*2<=cnt&&q[y*2].w<q[y].w)||(y*2<cnt&&q[y*2+1].w<q[y].w)){ if(y*2<cnt&&q[y*2+1].w<q[y*2].w)x=y*2+1; else x=y<<1; q[0]=q[x],q[x]=q[y],q[y]=q[0],y=x; } } }q; inline void add(int x,int y,int z){to[++last]=y,w[last]=z,next[last]=head[x],head[x]=last;} inline void dij(int x){ memset(vis,0,sizeof vis); dis[x][a[x]]=0,q.cnt=0,q.push(Node{0,a[x]}); while(true){ while(q.cnt&&vis[q.top().pos])q.pop(); if(!q.cnt)break; Node y=q.top(); vis[y.pos]=1; for(R int i=head[y.pos];i;i=next[i]) if(dis[x][to[i]]>y.w+w[i]) dis[x][to[i]]=y.w+w[i],q.push(Node{dis[x][to[i]],to[i]}); } } void dfs(int s){ if(s>k){ int mi=0x7ffffff,tot=0; for(R int i=1;i<k;++i)tot+=dis[b[i]][a[b[i+1]]]; for(R int i=1;i<=n;++i) if(!bj[i])mi=min(mi,dis[b[1]][i]+dis[b[k]][i]); for(R int i=1;i<=k;++i)printf("%d ",b[i]); printf("%d\n",tot); ans=min(ans,tot+mi); }else for(R int i=1;i<=k;++i) if(!vis[i])vis[i]=1,b[s]=i,dfs(s+1),vis[i]=0; } int main(){ R int x,y,z; read(n),read(m),read(k); for(R int i=1;i<=k;++i)read(a[i]),bj[a[i]]=i; for(R int i=1;i<=m;++i){ read(x),read(y),read(z); add(x,y,z),add(y,x,z); } memset(dis,0x3f,sizeof dis); for(R int i=1;i<=k;++i)dij(i); for(R int i=1;i<=k;++i)vis[i]=0; dfs(1); printf("%d",ans); }
    Processed: 0.014, SQL: 8