uva 10985 Rings'n'Ropes 解题报告

题意:题目意思看了好久才看懂

            有N个戒指,M条长度相同的绳子,然后双手任取两个戒指用力往左右拉,使得中间有些绳子会绷直,问最多能绷直的绳子条数?

分析:把戒指看成点,可知两个点拉长的长度必定是两点之间的最短距离,而拉直的线必定是最短距离上的。但是最短距离上的点之间的连线确不一定能绷直。

如下图:


1,2之间2,3之间能绷直,但是1,3之间不能绷直。 我们可以得出如果点对属于同一级则之间的线不能绷直(同一级指到起始点的距离相等),所以我们先做一遍Floyed,然后枚举左右的两个点,找出这两点最短路上的所有点,在枚举这些点对找能绷直的绳。

c++代码

#include<cstdio>
#include<cstring>
int a[150][150],s[150];
int f[150][150];
int n;
const int INF = 9999999;
void init()
{
    int m,i,j,x,y;
    scanf("%d%d",&n,&m);
    memset(a,0,sizeof(a));
    for (i = 1; i <= n; i++)
    for (j = 1; j <= n; j++)
        f[i][j] = INF;
    //
    for (i = 1; i <= m; i++)
    {
        scanf("%d%d",&x,&y);
        x++,y++;
        a[y][x] = a[x][y] = 1;
        f[x][y] = f[y][x] = 1;
    }
    for (i = 1; i <= n; i++)
    {
        f[i][i] = 0;
        a[i][i] = 1;
    }
}
void floyed()
{
    int k,i,j;
    for (k = 1; k <= n; k++)
    for (i = 1; i <= n; i++)
    for (j = 1; j <= n; j++)
    if (f[i][j] > f[i][k] + f[k][j])
        f[i][j] = f[i][k] + f[k][j];
}
void work()
{
    int i,j,k,k1,k2,tot,ans,ans1;
    ans = 0;
    for (i = 1; i <= n; i++)
    for (j = i+1; j <= n; j++)
    if (i != j && f[i][j] != INF)
    {
        tot = 0;
        ans1 = 0;
        for (k = 1; k <= n; k++)
            if (f[i][k] + f[k][j] == f[i][j]) s[++tot] = k;
        for (k1 = 1; k1 <= tot; k1++)
        for (k2 = k1 + 1; k2 <= tot; k2++)
        {
            if (a[s[k1]][s[k2]] == 1 && f[i][s[k1]] != f[i][s[k2]]) ans1++;
        }
        if (ans < ans1) ans = ans1;
    }
    printf("%d\n",ans);
}
int main()
{
    int temp,kase;
    scanf("%d",&temp);
    for (kase = 1; kase <= temp; kase++)
    {
        init();
        floyed();
        printf("Case #%d: ",kase);
        work();
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值