HDU 6005 Pandaland[最小生成树][LCA]

来源:互联网 发布:贝斯谱的软件 编辑:程序博客网 时间:2024/06/06 00:26

题意:给定 M 条边,找一个路径最短的环,如果不存在环,输出 0。其中(1M4000)

分析:通过观察可以发现,最短的环除去一条边外一定是在这个图的最小生成树上。
这样,我们可以通过枚举不在树上的边,求树上这条边的两点间距离,加上边的权值并取个最小值即可。
需要注意的是,题目给你的图可能有多个联通块。

以下是代码。

#include<bits/stdc++.h>using namespace std;#define ll long long#define ull unsigned long long#define lson l,mid,id<<1#define rson mid+1,r,id<<1|1typedef pair<int, int> pii;typedef pair<ll, ll> pll;const int INF = 0x3f3f3f3f;const ll LINF = 0x3f3f3f3f3f3f3f3f;const int MAXN = 10010;const int MAXM = 100005;const ll MOD = 998244353;const int maxn = 205 + 100;const double eps = 1e-8;const double PI = acos(-1.0);map<pii, int>mp;int tot;int pre[10005];int f[MAXN][20];int dep[MAXN];int val[MAXN];bool vis[MAXN];bool ss[MAXN];struct edge {    int u, v, cost;    edge(int _u = 0, int _v = 0, int _cost = 0) :u(_u), v(_v), cost(_cost) {}    bool operator<(const edge &a) {        return cost < a.cost;    }};struct to {    int v, cost;    to(int _v = 0, int _cost = 0) :v(_v), cost(_cost) {}};vector<to>vec[MAXN];vector<edge>v;int find(int x) { return x == pre[x] ? x : pre[x] = find(pre[x]); }void mix(int x, int y) {    int fx = find(x), fy = find(y);    if (fx != fy) {        pre[fx] = fy;    }}void kruskal() {    sort(v.begin(), v.end());    for (int i = 1; i <= tot; ++i)pre[i] = i;    for (int i = 0; i < v.size(); ++i) {        int posu = find(v[i].u), posv = find(v[i].v);        if (posu != posv) {            vis[i] = 1;            mix(posu, posv);            vec[v[i].u].push_back(to(v[i].v, v[i].cost));            vec[v[i].v].push_back(to(v[i].u, v[i].cost));        }    }}void dfs(int u, int pre,int now,int cur) {    ss[u] = 1;    val[u] = now;    dep[u] = cur;    f[u][0] = pre;    for (int i = 0; i < vec[u].size(); ++i) {        int vv = vec[u][i].v;        if (vv == pre)continue;        dfs(vv, u, now + vec[u][i].cost, cur + 1);    }}void getst() {    for (int i = 1; i < 20; ++i) {        for (int j = 1; j <= tot; ++j) {            f[j][i] = f[f[j][i - 1]][i - 1];        }    }}int getLca(int x, int y) {    if (dep[x]<dep[y]) swap(x, y);    for (int i = 19; i >= 0; i--){        if (dep[y] <= dep[f[x][i]]){            x = f[x][i];        }    }    if (x == y) return x;    for (int i = 19; i >= 0; i--){        if (f[x][i] != f[y][i]){            x = f[x][i];            y = f[y][i];        }    }    return f[x][0];}void init() {    memset(ss, 0, sizeof(ss));    memset(f, 0, sizeof(f));    memset(vis, 0, sizeof(vis));    v.clear();    tot = 0;    mp.clear();}int main() {    int m, T, cas = 0, a, b, c, d, e; scanf("%d", &T);    while (T--) {        init();        scanf("%d", &m);        for (int i = 0; i < m; ++i) {            scanf("%d%d%d%d%d", &a, &b, &c, &d, &e);            if (mp.count(pii(a, b)) == 0)mp[pii(a, b)] = ++tot;            if (mp.count(pii(c, d)) == 0)mp[pii(c, d)] = ++tot;            v.push_back(edge(mp[pii(a, b)], mp[pii(c, d)], e));        }        for (int i = 1; i <= tot; ++i)vec[i].clear();        kruskal();        for(int i=1;i<=tot;++i)if(!ss[i])dfs(i, 0, 0, 1);        getst();        int res = INF;        for (int i = 0; i < v.size(); ++i) {            if (!vis[i]) {                int lca = getLca(v[i].u, v[i].v);                res = min(res, val[v[i].u] + val[v[i].v] - 2 * val[lca] + v[i].cost);            }        }        if (res == INF)printf("Case #%d: 0\n", ++cas);        else printf("Case #%d: %d\n", ++cas, res);    }}
原创粉丝点击