春季测试 T3 最小生成树
  • 板块灌水区
  • 楼主uncesspath
  • 当前回复5
  • 已保存回复5
  • 发布时间2023/3/5 21:19
  • 上次更新2023/10/23 22:54:44
查看原帖
春季测试 T3 最小生成树
176205
uncesspath楼主2023/3/5 21:19

代码:

#include <iostream>
#include <algorithm>
#include <numeric>
#include <cstring>
#include <cmath>

const int MAXN = 1e3 + 5;
const int MAXM = 1e6 + 5;

int n, m = 1, k = 1;
double mmin = 0x3f3f3f3f;
int fa[MAXN], head[MAXN], path[MAXN];
bool vis[MAXM];
int deg[MAXN];

struct node
{
    double x, y;
} p[MAXN];

struct edge
{
    int u, v;
    double w;
} edges[MAXM];

int find(int x) { return x == fa[x] ? x : fa[x] = find(fa[x]); }

double dis(int i, int j) { return sqrt((p[i].x - p[j].x) * (p[i].x - p[j].x) + (p[i].y - p[j].y) * (p[i].y - p[j].y)); }

bool cmp(edge a, edge b) { return a.w < b.w; }

double Kruskal()
{
    double ans = 0;
    int cnt = 0;

    for (int i = 2; i <= m; i += 2)
    {
        if (cnt == n - 2) break;

        int u = edges[i].u, v = edges[i].v, w = edges[i].w;
        int r1 = find(u), r2 = find(v);

        if (r1 != r2 && u != k && v != k && (deg[u] < 2) && (deg[v] < 2))
        {
            fa[r1] = r2;
            ans += w;
            vis[i] = vis[i ^ 1] = true;
            deg[u]++;
            deg[v]++;
            cnt++;
        }
    }

    return ans;
}

void print()
{
    
    for (int i = 0; i < n; i++)
    {
        printf("%d ", path[i]);
    }
    printf("\n");
}

int main()
{
    // freopen("tree.in", "r", stdin);
    // freopen("tree.out", "w", stdout);

    scanf("%d", &n);
    for (int i = 1; i <= n; i++)
    {
        scanf("%lf %lf", &p[i].x, &p[i].y);
        if (p[i].y > p[k].y)
            k = i;
    }

    path[0] = k;

    for (int i = 1; i <= n; i++)
    {
        for (int j = i + 1; j <= n; j++)
        {
            if (i == j) continue;
            edges[++m].u = i;
            edges[m].v = j;
            edges[m++].w = dis(i, j);
            edges[m].u = j;
            edges[m].v = i;
            edges[m].w = edges[m - 1].w;
        }
    }

    std::stable_sort(edges + 2, edges + 1 + m, cmp);

    for (int i = 1; i <= n; i++)
    {
        if (i == k)
            continue;
        std::iota(fa + 1, fa + 1 + n, 1);
        memset(vis, 0, sizeof(vis));
        memset(deg, 0, sizeof(deg));
        fa[i] = k;
        deg[i]++;
        double ans = dis(i, k);
        ans += Kruskal();
        if (ans < mmin)
        {
            mmin = ans;
            int p = i;
            path[1] = i;
            for (int s = 2; s < n; s++)
            {
                for (int j = 2; j <= m; j++)
                {
                    if (edges[j].u == p && vis[j])
                    {
                        vis[j] = vis[j ^ 1] = false;
                        p = edges[j].v;
                        path[s] = p;
                        break;
                    }
                }
            }
        }
    }

    print();

    // fclose(stdin);
    // fclose(stdout);

    return 0;
}

肯定不是正解,但神奇的过掉了民间数据

2023/3/5 21:19
加载中...