【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
);
}