PAT甲级刷题实录——1013

原题链接

https://pintia.cn/problem-sets/994805342720868352/problems/994805500414115840

思路

题目大意是说一些城市之间有路相通,假设其中一个城市被敌方占领了,计算需要新修多少条路才能让剩下的城市全部联通。首先这是一个典型的图论问题,我们可以用邻接矩阵去存城市之间的联通关系。可以用深度遍历的思想去解决这个问题。思路大意如下:建立一个数组存储哪些城市已经被联通,1代表已联通,0代表未联通;定义一个变量记录需要新修的路的数量,该变量初值为-1。对所有结点进行for循环遍历,遍历到一个结点时,如果该节点还未联通,则需要新修的路的数量加1,并对该结点进行深度遍历以更新联通数组。变量初值为-1而不是0的原因是因为这个算法记录了和被攻占城市联通的一条路,需要去除掉该路。

代码

#include <iostream>
#include <vector>
using namespace std;
void updateReached(int start);
vector<int> reached;
vector<int> cWay;
vector<vector<int> > ways;
int main()
{
    int N, M, K;
    cin >> N >> M >> K;
    cWay.assign(N + 1, 0);
    ways.assign(N + 1, cWay);
    vector<int> result;
    for (int i = 0; i < M; i++)
    {
        int c1, c2;
        scanf("%d %d",&c1,&c2);
        ways[c1][c2] = 1;
        ways[c2][c1] = 1;
    }
    for (int i = 0; i < K; i++)
    {
        int newWayNum = -1;
        reached.assign(N + 1, 0);
        int checked;
        scanf("%d",&checked);
        reached[checked] = 1;
        for (int j = 1; j < N+1; j++)
        {
            if (reached[j] == 0)
            {
                updateReached(j);
                newWayNum++;
            }
        }
        printf("%d\n",newWayNum);
    }
}
void updateReached(int start)   //更新start可达的城市到reach列表
{
    reached[start] = 1;
    for (int i = 1; i < reached.size(); i++)
    {
        if (ways[start][i] == 1 && reached[i] == 0) //有路通且还没加入reached列表
        {
            updateReached(i);
        }
    }
    return;
}

这道题很坑的一点是一开始最后一个测试点一直运行超时,我还以为是算法逻辑出问题了,一直在找哪里有问题,找了半天找不出来。后来上网一查发现不少人都有运行超时的问题,原因是因为用了C++风格的输入输出方式cin和cout,这种输入输出方式的效率比scanf和printf低。解决方法就是改成scanf和printf

原文地址:https://www.cnblogs.com/aopstudio/p/12236907.html

时间: 2024-10-08 13:47:19

PAT甲级刷题实录——1013的相关文章

PAT甲级刷题实录——1004

原题链接 https://pintia.cn/problem-sets/994805342720868352/problems/994805521431773184 思路 很明显这题需要用到树这个数据结构,问题是怎么来存.一开始我是这样想的:因为它只问了每一层叶子结点数,所以最简单的情况下我只需要两个数据就行,一个是结点的所在的层级,另一个是结点是否含有子结点.所有的结点都存储在vector中,另外创建一个存储每一层叶子结点个数的数组用于最后输出结果.遍历vector,记录每一层不含有子结点的个

PAT甲级刷题实录——1011

原题链接 https://pintia.cn/problem-sets/994805342720868352/problems/994805504927186944 思路 这题就很简单了,每行输入的时候找出最大的记录下来,同时记录下标.输入完毕后根据下标转换成结果(W,T,L)并储存起来,再根据每行的最大值计算profit.最后输出结果和profit即可,代码如下. 代码 #include <iostream> #include <vector> using namespace s

PAT甲级刷题实录——1010

原题链接 https://pintia.cn/problem-sets/994805342720868352/problems/994805507225665536 思路 这题是到目前为止比较难的一题,评测系统的通过率也只有 0.11. 首先需要理解基本题意.题目的要求是给一个已知进制的数,求能不能找出一个进制使得另一个未知进制的数在该进制下和已知进制的数数值相等.大部分人应该都会想到将两个数的数值都转换为十进制后做比较. 在理解了基本题意之后,做的过程中发现这题还有不少坑. 进制是没有上限的.

PAT甲级刷题实录——1014

原题链接 https://pintia.cn/problem-sets/994805342720868352/problems/994805498207911936 思路 这题需要用到队列,而且不止一条.首先是每个等待窗口各需要一条,另外在黄线外的等待顾客需要一条.C++提供了现成了现成的队列类型,只要引用头文件queue即可. 算法基本运行过程是:在输入顾客等待时间时依次填满每条队列,超出队列容量的,即编号大于N*M+1的顾客,则push进黄线外的等待队列中.当有窗口有顾客处理完毕后,则将该顾

1085. Perfect Sequence (25)-PAT甲级真题

1085. Perfect Sequence (25) 时间限制 300 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CAO, Peng Given a sequence of positive integers and another positive integer p. The sequence is said to be a "perfect sequence" if M <= m * p where M and m

1020. Tree Traversals (25) PAT甲级真题

之前我看了这道题,实在是看不懂网上的解题答案,他们的具体思路基本上就是通过后续遍历和中序遍历,直接推出层次遍历. 我苦思冥想了半天,是在没看懂这种思路,于是想了一个笨点的但是也比较好理解的思路,通过后续和中序,先推出整个二叉树,再考虑 对二叉树层次遍历. 本题还有一点要注意的时在输出结果的末尾,如果使用了类似 pirntf("%d ",data); 这样的格式是不对的,一定要对末尾进行判断消除最尾端的空格. 首先最核心的部分是通过两次遍历反推回二叉树:这里的思路是,后续遍历的最末尾,一

1078. Hashing (25)-PAT甲级真题

1078. Hashing (25)The task of this problem is simple: insert a sequence of distinct positive integers into a hash table, and output the positions of the input numbers. The hash function is defined to be "H(key) = key % TSize" where TSize is the

PAT甲题题解-1111. Online Map (30)-PAT甲级真题(模板题,两次Dijkstra,同时记下最短路径)

题意:给了图,以及s和t,让你求s到t花费的最短路程.最短时间,以及输出对应的路径.   对于最短路程,如果路程一样,输出时间最少的. 对于最短时间,如果时间一样,输出节点数最少的.   如果最短路程和最短时间路径一样,合并输出一次即可. 纯粹就是练习dijkstra,没什么难的. 第一次dijkstra求最短路程,记录下每个节点的路程和时间. 第二次dijkstra求最短时间,记录下每个节点的时间和经过的节点数. pre数组用来存储前驱节点,保存路径 #include <iostream>

PAT甲级水题 A+B in Hogwarts(java string中分隔符的用法)

A+B in Hogwarts 在java.lang包中有String.split()方法,返回是一个数组 我在应用中用到一些,给大家总结一下,仅供大家参考: 1.如果用"."作为分隔的话,必须是如下写法,String.split("\\."),这样才能正确的分隔开,不能用String.split("."); 2.如果用"|"作为分隔的话,必须是如下写法,String.split("\\|"),这样才能正确