JZOJ 2933. 【NOIP2012模拟8.7】找位置
2024-10-20 20:47:55
题目大意
有 \(n(1 \leq n \leq 10000)\) 个城镇,由 \(1 \leq m \leq 50000\) 条无向道路连接。给出 \(k(1 \leq k \leq 5) 个超市\),现于剩下 \(n-k\) 个城镇中选择一个,使它到所有有超市的城镇再回来总路程最短
分析
注意到 \(k\) 很小,那我们就可以枚举经过这些超市的顺序,然后依次走最短路,再枚举一个另外出发城镇,由最后一个超市返回
于是就完了
\(Code\)
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int N = 10005 , M = 50005;
int n , m , k , tot , cnt;
int a[N] , used[10] , b[10] , order[200][10] , vis[N] , dis[10][N] , h[N];
struct edge{
int to , nxt , w;
}e[M << 1];
struct node{
int id , d;
bool operator < (node c) const {return d > c.d;}
};
priority_queue<node> q;
void add(int u , int v , int w){e[++tot] = edge{v , h[u] , w} , h[u] = tot;}
void dij(int s)
{
memset(vis , 0 , sizeof(vis));
for(register int i = 1; i <= n; i++) dis[s][i] = 1e8;
dis[s][a[s]] = 0;
while (!q.empty()) q.pop();
q.push((node){a[s] , 0});
while (!q.empty())
{
node x = q.top();
q.pop();
if (vis[x.id]) continue;
vis[x.id] = 1;
for(register int i = h[x.id]; i; i = e[i].nxt)
if (dis[s][x.id] + e[i].w < dis[s][e[i].to])
{
dis[s][e[i].to] = dis[s][x.id] + e[i].w;
q.push((node){e[i].to , dis[s][e[i].to]});
}
}
}
void dfs(int x)
{
if (x > k)
{
++cnt;
for(register int i = 1; i <= k; i++) order[cnt][i] = b[i];
return;
}
for(register int i = 1; i <= k; i++)
if (!used[i])
{
used[i] = 1 , b[x] = i , dfs(x + 1);
used[i] = 0 , b[x] = 0;
}
}
void solve()
{
int ans = 2e9;
dfs(1);
for(register int i = 1; i <= k; i++) dij(i);
memset(vis , 0 , sizeof vis);
for(register int i = 1; i <= k; i++) vis[a[i]] = 1;
for(register int i = 1; i <= cnt; i++)
{
int sum = 0;
for(register int j = 2; j <= k; j++) sum = sum + dis[order[i][j - 1]][a[order[i][j]]];
if (sum > ans) continue;
int Mi = 1e8;
for(register int j = 1; j <= n; j++)
if (!vis[j]) Mi = min(Mi , sum + dis[order[i][1]][j] + dis[order[i][k]][j]);
ans = min(ans , Mi);
}
printf("%d" , ans);
}
int main()
{
scanf("%d%d%d" , &n , &m , &k);
for(register int i = 1; i <= k; i++) scanf("%d" , &a[i]);
int u , v , w;
for(register int i = 1; i <= m; i++)
scanf("%d%d%d" , &u , &v , &w) , add(u , v , w) , add(v , u , w);
solve();
}
最新文章
- 解决“Dynamic Web Module 3.0 requires Java 1.6 or newer.”错误
- Java中private、protected、public和default的区别
- LINQ函数
- 【Java心得总结二】浅谈Java中的异常
- IIS发布项目 遇到的error
- [原]常用sqlserver数据库使用sql语句
- ubuntu手贱改了sudoers权限之后的恢复
- 14.约瑟夫环问题[JosephusProblem]
- OUYA设备的购买和安装
- 程序设计: 猫大叫一声,所有的老鼠都开始逃跑,主人被惊醒。(C#语言)
- python测试基于websocket协议的即时通讯接口
- Vue.jsbrowserify项目模板
- Vue2反向代理
- Oracle DB 总结(SQL)
- python装饰器同时支持有参数和无参数的练习题
- javascript中加号(+)操作符的作用
- MT【259】2016天津压轴题之最佳逼近
- SpringMvc的Url映射和传参案例(转)
- C#中将String类型保存到本地文件的方法
- 批处理/命令行合并js,递归合并子目录js文件
热门文章
- jquery &;&;、||
- 踩坑记录:Redis的lettuce连接池不生效
- Python中open()文件操作/OS目录操作
- MAUI新生4.6-主题设置LightTheme&;DarkTheme
- Vue3 企业级优雅实战 - 组件库框架 - 9 实现组件库 cli - 上
- Python 文件操作(IO 技术)
- Java基于内存的消息队列实现
- MQ系列10:如何保证消息幂等性消费
- 【Python】pip的镜像安装异常解决方案
- C#开发的资源文件程序(可国际化) - 开源研究系列文章