GDCPC 2008:B Reading books

Problem B

Reading books

(Input File: book.in / Standard Output)

 

In the summer vacation, LRJ wants to improve himself in computer science. So he finds out N books of computer science in the school library. The books are numbered from 0 to N-1.

To finish reading the i-th book, it takes LRJ time[i] minutes. But some books are similar in the content. If the i-th book and the j-th book are similar, then if LRJ has finished reading the i-th book, it will take him only  minutes to finish reading the j-th book. Of course if LRJ has finished reading the j-th book, it will take him only  minutes to finish reading the i-th book. Now you are asked to tell LRJ the minimal total time to finish reading all the N books.

 

Input:

The first line contains two integers N (0<=N<=100) and M (0<=M<=N*(N-1)/2). N is the total number of books. M is the number of pairs which are similar.

Then the following N lines describe time[0], time[1], … , time[N-1] (1<=time[i]<=105).

Next comes M lines, each contains two integer (i, j), indicating that the i-th book and the j-th book are similar.

Input is ended by N=0 and M=0.

 

Output:

For each test case, just output the minimal total time on a single line.

 

Sample input:

2 1

6

10

0 1

3 2

1

2

3

0 1

1 2

3 1

2

4

6

0 1

0 0

 

Sample output:

11

3

10

 

Hints:

For the first test case, if LRJ read the books in the order (0, 1), then the total time = 6+10/2=11; If in the order (1, 0), then the total time =10+ 6/2=13.

 

用矩阵将所有相似的书都标记起来,然后通过dfs去算和即可

 

#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;

int map[105][105],val[105],n,m,sum,minn;
int vis[105],ans;

void dfs(int x)
{
    vis[x] = 1;
    sum+=val[x]/2;
    if(minn == -1 || val[x]<minn)
        minn = val[x];
    for(int i = 0; i<n; i++)
    {
        if(!vis[i] && map[x][i])
            dfs(i);
    }
}

int main()
{
    int i,x,y;
    while(~scanf("%d%d",&n,&m),n+m)
    {
        memset(map,0,sizeof(map));
        memset(vis,0,sizeof(vis));
        ans = 0;
        for(i = 0; i<n; i++)
            scanf("%d",&val[i]);
        for(i = 0; i<m; i++)
        {
            scanf("%d%d",&x,&y);
            map[x][y] = map[y][x] = 1;
        }
        for(i = 0; i<n; i++)
        {
            minn = -1;
            if(vis[i])
                continue;
            sum = 0;
            dfs(i);
            ans = ans+sum-minn/2+minn;
        }
        printf("%d\n",ans);
    }

    return 0;
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值