【问题标题】:Capital Movement | Competitive Programming资本运动 |竞争性编程
【发布时间】:2017-01-09 22:36:32
【问题描述】:

问题

假设一个国家有“n”个城市,其中一个是首都。所有城市都通过“n-​​1”条道路连接起来,使用这些道路可以在任何两个城市之间旅行。问题中提供了城市人口 Pi

现在,如果一个城市感染了病毒,那么与该城市相连的城市也会被感染。在感染的情况下,选择一个新的首都。人口最多的未感染城市成为新首都。

输入

输入的第一行包含一个整数 T,表示测试用例的数量。 T测试用例的描述如下。

每个测试用例的第一行包含一个整数N,表示城市数。

下一行包含 N 个以空格分隔的整数 P1、P2、...、PN,表示每个城市的人口。

接下来的 N-1 行包含两个以空格分隔的整数,每个 V 和 U 表示城市 V 和 U 之间有一条道路。

输出

对于每个测试用例,输出一行,其中包含 N 个整数 A1、A2、...、AN,以空格分隔。这里 Ai 表示在感染开始从城市 i 蔓延的情况下被选为新首都的城市数量。万一感染影响所有城市输出0。

示例

输入

1

6

5 10 15 20 25 30

1 3

2 3

3 4

4 5

4 6

输出

6 6 6 2 6 5

我的 C++ 解决方案

#include <iostream>
#include <vector>
#include <list>
#include <stdio.h>
#include <algorithm>
using namespace std;

int main() {
    int t;
    scanf("%d", &t); //No. of test cases
    while(t--) {
        int n;
        scanf("%d", &n);
        vector<int> p(n);   //vector for storing population of each city
        for(int i = 0; i < n; i++)
            scanf("%d", &p[i]);

        vector<list<int> > graph(n); //vector of lists for storing connection between cities


        for(int i = 0; i < n-1; i++) { 
            int a, b;
            scanf("%d %d", &a, &b);
            graph[--a].push_back(--b);
            graph[b].push_back(a);
        }

        for(int i = 0; i < n; i++) {
            vector<int> temp = p;             //Temporary vector 

        /*All the infected cities are assigned a population
          of -1 so that they don't compete to become the largest capital*/

            temp[i] = -1;
            if(graph[i].size() == n-1) {//Printing "0" if all cities have connection with the infected city.
                cout<<"0 ";
                continue;
            }
            int s = graph[i].size();
            for(int j = 0; j < s; j++) {
                temp[graph[i].front()] = -1;
                graph[i].pop_front();
            }

            /*Finding max. population*/
            int maxindex = std::distance(temp.begin(), std::max_element(temp.begin(), temp.end()));

            printf("%d ", maxindex+1);
        }
        printf("\n");
    }
    return 0;
} 

函数 max_element 使时间复杂度成为二次方。 我的解决方案是超出大输入的时间限制。因此,我的程序需要改进执行时间。请帮忙。感谢您的宝贵时间。

【问题讨论】:

  • 请拨打Tour。你的问题对我来说似乎是题外话。您在寻找Code Review 吗?
  • @Gyanshu 您应该编辑您的代码以将数据硬编码到您的程序中。如果您发布的是测试数据,则不需要scanf 调用。这允许其他愿意帮助的人轻松复制和粘贴您的代码并运行它,而无需每次都输入数据。
  • @Gyanshu 另外,为什么有这么多循环来复制数据?这个:for(int j = 0; j &lt; n; j++) { temp[j] = p[j];} 就是这个:temp = p;.没有任何 for 循环
  • @Gyanshu 还有maxindex = std::distance(temp.begin(), std::max_element(temp.begin(), temp.end());——不需要循环来计算maxindex(因此,max)。
  • @PaulMcKenzie 虽然你提到的这两件事都会稍微缩短我的代码,但不会影响我的代码在执行时占用的时间或空间。

标签: c++ algorithm performance time-complexity space-complexity


【解决方案1】:

因为没有关于“更大的投入”意味着什么的信息,我猜它指的是拥有更多的城市。在这种情况下,您正在制作一个巨大的(nxn)图形数组,这将导致更多内存被占用,同时(大部分)是空的,因为只有 n-1 条道路。 考虑使用 std::list 连接城市,然后仅查找与受感染城市不在同一列表中的城市。

【讨论】:

  • 虽然该图占用更多内存,但它还提供 O(1) 访问权限以了解哪些城市将被特定城市病毒感染。如果是列表,时间复杂度将是线性的。
  • @Gyanshu:目前,您正在遍历每个城市以查看它是否已连接。浏览已连接城市的列表将花费更少的时间。
  • @Kundor 你也许是对的,但它会影响时间复杂度吗,因为在最坏的情况下,被感染的城市可能与其他所有城市相连。
  • @Gyanshu:在这种情况下,遍历连接城市列表中的所有 n 个城市与像您已经在做的那样遍历所有 n 个城市是一样的。
  • @Kundor 知道了,你们俩都是对的。让我检查一下更改是否可以解决我的问题。
【解决方案2】:

解决了!诀窍是事先对城市人口进行分类

#include <iostream>
#include <vector>
#include <list>
#include <stdio.h>
#include <algorithm>
using namespace std;
bool myfnc(pair<int, int> i, pair<int, int> j) {
    return i.first > j.first;
}
int main() {
    int t;
    scanf("%d", &t);
    while(t--) {
        int n, d;
        scanf("%d", &n);
        vector<int> p(n);
        int m = 0, mi = 0;
        for(int i = 0; i < n; i++) {
            scanf("%d", &d);
            p[i] = d;
        }
        vector<pair<int, int> > p1(n);
        for(int i = 0; i < n; i++) {
            p1[i].first = p[i];
            p1[i].second = i;
        }
        sort(p1.begin(), p1.end(), myfnc);

        vector<vector<bool> > graph(n, vector<bool> (n));
        for(int i = 0; i < n-1; i++) {
            int a, b;
            scanf("%d %d", &a, &b);
            graph[--a][--b] = 1;
            graph[b][a] = 1;
            graph[i][i] = 1;
        }
        graph[n-1][n-1] = 1;
        for(int i = 0; i < n; i++) {
            int j;
            for(j = 0; j < n; j++) {
                if(graph[i][p1[j].second] == 0) {
                    printf("%d ", p1[j].second+1);
                    break;
                }
            }
            if(j == n)
                printf("0 ");
        }
        printf("\n");
    }
    return 0;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-04-25
    • 2019-02-15
    • 1970-01-01
    • 2023-03-08
    • 1970-01-01
    • 1970-01-01
    • 2015-02-02
    • 2021-01-07
    相关资源
    最近更新 更多