HDU 3768 Shopping 【最短路好题!!! + 离散化跑最短路 + 暴力枚举】

传送门
// 题题: 给定一个无向图(n, m) , 和 s 个必经点, 问从起点1出发必经给s个点后再回到1的路径之和最小是多少.

// 思路: 这道题和我之前做的一道题很像, 所以我做这道题的时候几乎是秒做吧……xixi
我们首先有一个想法就是一定是这s个点先相互到达, 然后在从中选择两个到1最短距离加上就行啦. 然后可以注意到s只有10, 那么我们直接跑10次dij(优化的), 统计出该10个点到图中任意一个点的最短路径, 因为点的编号很大, 所以进行一次离散化就行啦, 然后我们直接暴力循环这10个点的所有情况, 也就是全排列一次, 然后每次用第一个和最后一个和1的最短距离相加, 中间的相加取一个最小的就是了, 一定可以出答案的. 具体细节请看代码.

AC Code

const ll INF = 1e18;
const int maxn = 1e5+5;
int cas=1;
int cnt, head[maxn];
struct node
{
    int to, next; ll w;
    bool operator < (const node& a) const {
        return w > a.w;
    }
} e[maxn<<1];

void add(int u, int v, ll w) {
    e[cnt] = (node){v,head[u],w};
    head[u] = cnt++;
}

void init() {
    cnt = 0;
    memset(head, -1, sizeof(head));
}

bool vis[maxn];
ll dis[15][maxn];
int n,m;
void dij(int st, int cnt)
{
    priority_queue q;
    for (int i = 1 ; i <= n ; i ++) dis[cnt][i] = INF;
    dis[cnt][st] = 0; Fill(vis,0);
    q.push((node){st, 0, 0});
    while (!q.empty()) {
        node u = q.top();
        q.pop();
        if(vis[u.to]) continue;
        vis[u.to] = 1;

        for (int i = head[u.to]; ~i; i = e[i].next) {
            node k = e[i];
            if (dis[cnt][k.to] > dis[cnt][u.to] + k.w) {
                dis[cnt][k.to] = dis[cnt][u.to] + k.w;
                q.push((node){k.to, 0, dis[cnt][k.to]});
            }
        }
    }
}
int f[15], v[15];
void solve()
{
    init();
    scanf("%d%d",&n, &m);
    for (int i = 1 ; i <= m ; i ++) {
        int u, v; ll w;
        scanf("%d%d%lld", &u, &v, &w);
        u++; v++;
        add(u, v, w); add(v, u, w);
    }
    int q; scanf("%d", &q);
    for (int i = 1 ; i <= q ; i ++) {
        int x; scanf("%d",&x);
        x++; dij(x, i);
        f[i] = i; v[i] = x;  // 离散化点.并跑最短路
    }
    sort(f+1, f+1+q);
    ll ans = INF;
    do {
        ll tmp = dis[f[1]][1];
        for (int i = 2 ; i <= q ; i ++) {
            tmp += dis[f[i]][v[f[i-1]]];
        }
        tmp += dis[f[q]][1];
        ans = min(ans, tmp);
    }while(next_permutation(f+1, f+1+q));  // 暴力所有情况.
    printf("%lld\n", ans);
}

你可能感兴趣的:(最短路相关)