usaco Fence Loops

1.floyd求最小环。设环中有最大编号的点为k,其邻接点为i,j,则以k为环最大编号点的环的最小长度为

answer = g[k][i] + g[k][j] + i到j的最短路[路径中的节点编号小于k]

2.构造图(难点)。

输入边的信息。

len[i] 记录第i条边的长度

边表 adj[n][2][n]记录第i条边第0、1端第j条边的编号

edge[i][2] 记录第i条边两端邻接的边数

matrix[i][j] 记录第j条边位于第i条边的哪一端

g[i][j] 用于表示邻接矩阵

dist[i][j] 记录最短路径

思路:

输入边的信息,然后用matrix记录各个边之间的关系,枚举边对其两端点构造节点编号,并更新其邻接边的相应的端点的

节点编号,然后通过floyd求最短路求出最小环的长度

参考:dd usaco
/*
 ID: daijinq1
 PROB:fence6
 LANG: C++
 */
#include <iostream>
#include <algorithm>
#include <sstream>
#include <cstring>
#include <cstdio>
using namespace std;

#define FOR(i,a,b) for(i = (a); i < (b); ++i)
#define FORE(i,a,b) for(i = (a); i <= (b); ++i)
#define FORD(i,a,b) for(i = (a); i > (b); --i)
#define FORDE(i,a,b) for(i = (a); i >= (b); --i)
#define CLR(a,b) memset(a,b,sizeof(a))

const int MAXN = 110;
const int INF = 0x7f7f7f7f;
int N;
int cnt;
int end;
int answer;
int len[MAXN];
int adj[MAXN][2][MAXN];
int edge[MAXN][2];
int matrix[MAXN][MAXN];
int edge_point[MAXN][2];
int g[MAXN][MAXN];
int dist[MAXN][MAXN];

void floyd() {
    int i, j, k;

    answer = 10000000;
    FOR(i, 1, cnt) FOR(j, 1, cnt)
        dist[i][j] = g[i][j];
    FOR(k, 1, cnt) {
        FOR(i, 1, k) FOR(j, i + 1, k)
            answer = min(answer, g[i][k] + g[k][j] + dist[i][j]);
        FOR(i, 1, cnt) FOR(j, 1, cnt)
            dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);
    }
}

void makepoint(int l, int side, int cnt) {
    int i;

    edge_point[l][side] = cnt;
    FORE(i, 1, edge[l][side]) {
        int x = adj[l][side][i];
        if(matrix[x][l] == 0)
            edge_point[x][0] = cnt;
        else
            edge_point[x][1] = cnt;
    }
}

void makegraph() {
    int i, j;

    cnt = 1;
    CLR(edge_point, -1);
    FORE(i, 1, N) {
        if(edge_point[i][0] == -1)
            makepoint(i, 0, cnt++);
        if(edge_point[i][1] == -1)
            makepoint(i, 1, cnt++);
    }
    FOR(i, 1, cnt) FOR(j, 1, cnt)
        g[i][j] = 10000000;
    FORE(i, 1, N)
        g[edge_point[i][0]][edge_point[i][1]] = g[edge_point[i][1]][edge_point[i][0]] = len[i];
    floyd();
    printf("%d\n", answer);
}

void input() {
    int i, j, k, l;

    scanf("%d", &N);
    FORE(i, 1, N) {
        scanf("%d", &l);
        scanf("%d %d %d ", &len[l], &edge[l][0], &edge[l][1]);
        FORE(k, 0, 1)
        FORE(j, 1, edge[l][k]) {
            scanf("%d", &adj[l][k][j]);
            matrix[l][adj[l][k][j]] = k;
        }
    }
}

int main() {
    freopen("fence6.in", "r", stdin);
    freopen("fence6.out", "w", stdout);
    input();
    makegraph();
    floyd();
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值