目录
这道题用拓扑排序,但是在建图的时候,用领接矩阵很可能会TML,所以用领接表。
偷偷告诉你,如果硬要用领接矩阵,定义一个bool类型的二维数组建图就不会TML啦。
咳咳,来看下面
简单明了的比较
自己写领接表,写那堆函数
用vector
你看看这时间和空间,用vector都要优于不用
看看代码
不用的
#include<iostream>
#include<queue>
#include<algorithm>
#define ll long long
using namespace std;
const int N = 10002;
int n;
int num[N],in[N],f[N];
//in是入度 指进来
queue<int>s;
ll ans=0;
ll max(ll x, int y) {
return x > y ? x : y;
}
typedef struct node {
int y;
struct node* next;
}node;
typedef struct list {
int head;
node* n;
}list;
list g[N];
void init() {
for (int i = 1; i <= n; i++) {
g[i].head = i;
g[i].n = nullptr;
}
}
void insert(int i) {
int c;
while (cin >> c) {
if (c == 0) {
return;
}
node* new_ = new node;
new_->y = i;
new_->next = g[c].n;
g[c].n = new_;
}
}
int find(int m,int j) {
node* a = g[m].n;
while (a != nullptr) {
if (a->y == j) {
return 1;
}
a = a->next;
}
return 0;
}
int main()
{
cin >> n;
init(); //初始化
for (int i = 1; i <= n; i++) { //插入
int a, b, c;
cin >> a >> b;
num[a] = b;
insert(a);
}
for (int i = 1; i <= n; i++) {
if (in[i]==0) {
s.push(i);
f[i] = num[i];
}
}
while (!s.empty()) { //拓扑
int m = s.front();
s.pop();
for (int j = 1; j <= n; j++) {
if (find(m,j)) {
in[j]--;
if (in[j] == 0)s.push(j);
f[j] = max(f[j], f[m] + num[j]);
ans = max(ans, f[j]);
}
}
}
cout << ans;
return 0;
}
用了的
#include<iostream>
#include<queue>
#include<algorithm>
#include<vector>
#define ll long long
using namespace std;
const int N = 10002;
int n;
int num[N],in[N],f[N];
//in是入度 指进来
queue<int>s;
vector<int>to[N];
ll ans=0;
ll max(ll x, int y) {
return x > y ? x : y;
}
int main()
{
cin >> n;
for (int i = 1; i <= n; i++) {
int a, b, c;
cin >> a >> b;
num[a] = b;
while (cin >> c) {
if (c == 0)break;
to[c].push_back(a);
in[a]++;
}
}
for (int i = 1; i <= n; i++) {
if (in[i]==0) {
s.push(i);
f[i] = num[i];
}
}
while (!s.empty()) {
int now = s.front();
s.pop();
for (int j = 0; j < to[now].size(); j++) {
int cnt = to[now][j];
f[cnt] = max(f[cnt], f[now] + num[cnt]);
ans = max(ans, f[cnt]);
in[cnt]--;
if (in[cnt] == 0)s.push(cnt);
}
}
cout << ans;
return 0;
}
怎么样,一下子简洁太多了,对吧,还很简单
为什么这么好?
vector源代码放这里了
https://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/include/bits/stl_vector.h
我看了看,哈哈,难搞——
直接说明原因吧
对于下面的第一点和第二个点,我们每次分配内存,一个一个new,浪费时间,而假如我一次new要一堆,我们要知道,new运算符首先在堆区分配足够的内存快,接着调用构造函数,我可以一次性调用构造函数来初始化,这是其一。内存对齐: 分配多个对象时,编译器可能会更好地管理内存对齐,从而减少内存浪费。这是其二。
内存分配策略:
std::vector
在进行内存分配时,通常会分配一块稍微比当前大小大一些的内存,以便能够容纳未来的元素插入。这避免了每次插入元素都要重新分配内存的情况,从而提高了性能。连续内存存储:
std::vector
使用连续的内存块存储元素,这可以提供更好的缓存局部性,从而减少访问内存的开销。相比之下,链式结构的邻接表需要更多的内存以存储指针。访问时间复杂度: 使用
std::vector
的直接索引访问元素的时间复杂度是 O(1),而在链表中查找元素需要线性时间,因此在寻找邻接节点时std::vector
更高效。空间效率: 由于使用
std::vector
的数据结构是紧凑的连续内存块,相对于链式结构的邻接表,它不需要额外的指针和链表节点开销,因此可能更加节省空间。
对vector的理解
std::vector
就是在数组的基础上进行了封装,使其具有了动态大小的能力。它可以看作是动态数组,因为它使用数组的连续内存存储和随机访问的优势,同时又能够在需要时自动扩展内存,实现动态的插入和删除。与链表不同的是,
std::vector
的内部实现并不是用指针来连接节点,而是通过动态调整数组的大小和复制元素来实现插入和删除。这使得std::vector
在随机访问上更为高效,但在插入和删除方面可能相对较慢。
至于语法,这里就不过多赘述了——
有机会还是啃啃源代码了
下面是chatGPT给的简单的实现
#include <iostream>
#include <stdexcept>
template <typename T>
class Vector {
private:
T* arr;
size_t size;
size_t capacity;
public:
Vector() : arr(nullptr), size(0), capacity(0) {}
Vector(size_t initialSize) : arr(new T[initialSize]), size(0), capacity(initialSize) {}
~Vector() {
delete[] arr;
}
void push_back(const T& value) {
if (size == capacity) {
resize(capacity * 2 + 1);
}
arr[size++] = value;
}
T& at(size_t index) {
if (index >= size) {
throw std::out_of_range("Index out of range");
}
return arr[index];
}
size_t getSize() const {
return size;
}
size_t getCapacity() const {
return capacity;
}
private:
void resize(size_t newSize) {
T* newArr = new T[newSize];
for (size_t i = 0; i < size; ++i) {
newArr[i] = arr[i];
}
delete[] arr;
arr = newArr;
capacity = newSize;
}
};
int main() {
Vector<int> vec;
vec.push_back(10);
vec.push_back(20);
vec.push_back(30);
for (size_t i = 0; i < vec.getSize(); ++i) {
std::cout << vec.at(i) << " ";
}
return 0;
}
现在的我就是,看不见代码实现,我就难受哈哈哈哈
祝AC,拜拜~