TC DIV I 500分题目的解答(算法:有向图的强连通)

来源:互联网 发布:时空幻境知乎 编辑:程序博客网 时间:2024/05/17 03:33

武汉白云黄鹤站∶精华区
发信人: Sempr (偶尔||sigh~), 信区: Algorithm
标  题: TC DIV I 500分题目的解答(算法:有向图的强连通)
发信站: 武汉白云黄鹤站 (2006年07月23日11:31:18 星期天), 站内信件
 
 
2006年07月22号的SRM 312
 
题意是有N个小镇,某些小镇之间有单向的道路相连
要在这些小镇中的部分地方建立警察局,要保证对于任意一个小镇,可以找到最少一个警
察局,从这个警察局有路到达该小镇
 
在每个小镇建立一个警察局的费用是不同的,要你求出如何在这个N个小镇建立警察局,
使建立一个警察局的平均费用最低,要求输出这个最低的费用。
 
 
比赛的时候我理解错了题意,直接用了贪心,后来听yzf说是错了,果然在cha的时候就被
别人给搞掉了,郁闷....
 
今天早上起来重新写了一下代码,并且通过了全部的系统测试
 
题目的解法是:
 
先求出这一个图的强连通分量,然后在所有入度为0的连通分量的内部中费用最低的点上
建立警察局,但这样只能保证总费用最低,但不能保证平均费用最低
 
下一步要做的就是将所有的没建立警察局的小镇按费用从低到高进行排序,然后判断将
当前费用最低的点加入会不会使平均费用减小,如果减小,那么把这点加入,并继续判
断下一个点,如果当前的值比平均值要大,那么加上这个点也没有用了,之后的点的费
用都要比当前这个点大,所以加上它们也是没用的,循环就此结束。此时得到的值就是
题目要求的结果
 
以下是题目描述和通过了系统测试的代码
 
 
Problem Statement
 
Year 2100. Humanity is starting to inhabit Antarctica. So far there are N
towns, some of them connected with narrow one-way roads.
The president of Antarctica has decided to establish police in his country.
The cost of building a police station in each town is given. However, there
may not be a need to build a police station in every town. The only
requirement is that every town must be reachable from some police station
using roads.
As the next elections are approaching, the president doesn't want to expose
large police expenses. Thus he wants the average cost of a built station to
be as low as possible.
You are given a int[] costs, the i-th element of which represents the cost of
building a police station in town i, and a String[] roads representing the
layout of the one-way roads. The j-th character of the i-th element of roads
is 'Y' if there is a road from town i to town j, or 'N' if there is not. Make
the average cost of a built station to be as low as possible and return this
cost.
Definition
Class:
AntarcticaPolice
Method:
minAverageCost
Parameters:
vector <int>, vector <string>
Returns:
double
Method signature:
double minAverageCost(vector <int> costs, vector <string> roads)
(be sure your method is public)
 
Notes
-
The returned value must be accurate to within a relative or absolute error of
1E-9.
Constraints
-
costs will contain between 1 and 50 elements, inclusive.
-
Each element of costs will be between 1 and 1000, inclusive.
-
roads will contain exactly N elements, where N is the number of elements in
costs.
-
Each element of roads will contain exactly N characters.
-
Each character of each element of roads will be 'Y' or 'N'.
-
The ith character of the ith element of roads will be 'N'.
Examples
0)
 
????
{1,2,3,4}
{"NYNN","NNYN","NNNY","YNNN"}
Returns: 1.0
It is possible to get everywhere from anywhere (the towns form a big circle),
so we need only the cheapest station.
 
1)
 
{1,2,3,4}
{"NYNN","NNYN","NNNY","NYNN"}
Returns: 1.0
Once again, the cheapest station is enough.
 
2)
 
{5,6,7,8}
{"NYNN","YNNN","NNNY", "NNYN"}
Returns: 6.0
We have two separate parts, so we build one cheapest station in each part :
(5+7)/2=6.
 
3)
 
{10,5}
{"NY","NN"}
Returns: 7.5
We have three choices here: build a police station in town 0, in town 1, or
in both towns. The second choice doesn't satisfy the requirements since it's
impossible to get from town 1 to town 0. Of the two remaining choices,
building both is better because it minimizes the average cost.
 
4)
 
{34,22,25,43,12}
{"NYNNY","YNNYN","NNNYY","NNNNN","NNNNN"}
Returns: 19.666666666666668
 
This problem statement is the exclusive and proprietary property of TopCoder,
Inc. Any unauthorized use or reproduction of this information without the
prior written consent of TopCoder, Inc. is strictly prohibited. (c)2003,
TopCoder, Inc. All rights reserved. 
 
//code
#include <algorithm>
#include <vector> 
#include <string> 
#include <memory.h> 
#include <iostream>
using namespace std;
 
class AntarcticaPolice
{
    static const int SIZE = 60;
    int p[SIZE][SIZE], vis[SIZE], order[SIZE], id[SIZE];
    int in[SIZE], minid[SIZE], min[SIZE];
    int cnt, N, N_s;
 
    void DFS1(int x)
    {
        int i;
        vis[x] = 1;
        for (i = 0; i < N; i++)
        {
            if (vis[i] == 0 && p[x][i])
                DFS1(i);
        }
        order[cnt++] = x;
    }
 
    void DFS2(int x)
    {
        int i;
        vis[x] = 1;
        id[x] = cnt;
        for (i = 0; i < N; i++)
        {
            if (vis[i] == 0 && p[i][x])
                DFS2(i);
        }
    }
 
    public:
    double minAverageCost(vector <int> costs, vector <string> roads)
    {
        int i, j, sum, tmpN;
        N = costs.size();
        //建图
        for (i = 0; i < N; i++)
        {
            for (j = 0; j < N; j++)
            {
                p[i][j] = roads[i][j] == 'Y' ? 1 : 0;
            }
        }
        //求强连通分量
        memset(vis, 0, sizeof(vis));
        cnt = 0;
        for (i = 0; i < N; i++)
            if (!vis[i]) DFS1(i);
        cnt = 0;
        memset(vis, 0, sizeof(vis));
        for (i = N - 1; i >= 0; i--)
        {
            if (!vis[order[i]])
            {
                DFS2(order[i]);
                cnt++;
            }
        }
        N_s = cnt;
        //求入度
        memset(in, 0, sizeof(in));
        for (i = 0; i < N; i++)
        {
            for (j = 0; j < N; j++)
            {
                if (p[j][i] && id[i] != id[j])
                    in[id[i]]++;
            }
        }
        //求每个分量的最小值点
        memset(min, 1100, sizeof(min));
        for (i = 0; i < N; i++)
        {
            if (costs[i] < min[id[i]])
            {
                minid[id[i]] = i;
                min[id[i]] = costs[i];
            }
        }
        //对入度为0的点中的最小值进行求和
        memset(vis, 0, sizeof(vis));
        sum = 0;
        cnt = 0;
        for (i = 0; i < N_s; i++)
        {
            if (in[i] == 0)
            {
                vis[minid[i]] = 1;
                sum += min[i];
                cnt++;
            }
        }
        //对其他点进行排序并贪心求和
        for (i = 0, j = 0; i < N; i++)
        {
            if (!vis[i])
                order[j++] = costs[i];
        }
        tmpN = N - cnt;
        sort(order, order + tmpN);
        for (i = 0; i < tmpN; i++)
        {
            if (sum > cnt * order[i])
            {
                sum += order[i];
                cnt++;
            }
            else
            {
                break;
            }
        return sum * 1.0 / cnt;
    }
};
 
--
    看过浮华喧闹,走过纷纷扰扰
        有人哭,有人笑,都逃不出自己的牢
            太想得到得不到,得不到的更想要
                到最后才知道,名名利利是煎熬
                                                                                           
※ 修改:·Sempr 于 07月23日11:35:37 修改本文·[FROM: bbs.whnet.edu.cn]
※ 来源:·武汉白云黄鹤站 bbs.whnet.edu.cn·
※ 来源:·武汉白云黄鹤站 bbs.whnet.edu.cn·

华中地区网络中心 

原创粉丝点击