perf(P9981): 优化图算法性能并实现快速IO

重构图遍历算法,使用更高效的数据结构和比较逻辑
添加FastIO模块提升输入输出性能
This commit is contained in:
Zengtudor 2025-09-10 21:23:33 +08:00
parent 88b393ac28
commit 8c8fc92b3b

View File

@ -1,107 +1,196 @@
#include <algorithm> #include <algorithm>
#include <cstdint>
#include <iostream> #include <iostream>
#include <istream>
#include <queue> #include <queue>
#include <tuple>
#include <vector> #include <vector>
using ll = int64_t;
ll n,m; namespace FastIO {
const int BUF_SIZE = 1 << 20;
char in_buf[BUF_SIZE], out_buf[BUF_SIZE];
char *in_ptr = in_buf + BUF_SIZE;
char *out_ptr = out_buf;
char get_char() {
if (in_ptr == in_buf + BUF_SIZE) {
fread(in_buf, 1, BUF_SIZE, stdin);
in_ptr = in_buf;
}
return *(in_ptr++);
}
template <typename T> void read(T &x) {
x = 0;
char c = get_char();
bool positive = true;
while (!isdigit(c)) {
if (c == '-')
positive = false;
c = get_char();
}
while (isdigit(c)) {
x = x * 10 + (c - '0');
c = get_char();
}
if (!positive)
x = -x;
}
void put_char(char c) {
if (out_ptr == out_buf + BUF_SIZE) {
fwrite(out_buf, 1, BUF_SIZE, stdout);
out_ptr = out_buf;
}
*(out_ptr++) = c;
}
template <typename T> void write(T x) {
if (x < 0) {
put_char('-');
x = -x;
}
if (x == 0) {
put_char('0');
return;
}
char buf[20];
int len = 0;
while (x > 0) {
buf[len++] = (x % 10) + '0';
x /= 10;
}
for (int i = len - 1; i >= 0; --i) {
put_char(buf[i]);
}
}
struct Flusher {
~Flusher() {
if (out_ptr != out_buf) {
fwrite(out_buf, 1, out_ptr - out_buf, stdout);
}
}
} flusher;
} // namespace FastIO
using FastIO::put_char;
using FastIO::read;
using FastIO::write;
struct Edge { struct Edge {
ll to,l; int to;
int label;
}; };
std::vector<std::vector<Edge>> edg;
std::vector<ll> ind;
std::queue<ll> q;
std::vector<ll> topo;
std::vector<ll> len;
std::vector<std::vector<ll>> lv;
#define p1v(ind)do{\ struct Path {
std::cout<<#ind<<"\n";\ long long len = 0;
for(auto& i:ind){\ long long sum = 0;
std::cout<<i<<", ";\ int prefix_label = 0;
}\ int next_node = 0;
std::cout<<"\n";\ };
}while(0)
namespace std{ bool is_better(const Path &p_cand, const Path &p_best, const std::vector<Path> &dp) {
static inline bool operator<(const vector<ll>&a,const vector<ll>&b){ if (p_cand.len > p_best.len)
if((a.size()|b.size()) == 0){
return false;
}
if(a.size()==0 && b.size()!=0){
return true; return true;
} if (p_cand.len < p_best.len)
if(a.size()!=0 && b.size() == 0){
return false; return false;
}
for(ll i=0;i<a.size()&&i<b.size()&&i<500;i++){ if (p_cand.len == 0)
if(a[i]<b[i])return true; return false;
else if(a[i]>b[i])return false;
} if (p_cand.prefix_label < p_best.prefix_label)
return a.size()<b.size(); return true;
} if (p_cand.prefix_label > p_best.prefix_label)
return false;
const Path *ptr1 = &dp[p_cand.next_node];
const Path *ptr2 = &dp[p_best.next_node];
for (int i = 0; i < 110 && ptr1->len > 0 && ptr2->len > 0; ++i) {
if (ptr1->prefix_label < ptr2->prefix_label)
return true;
if (ptr1->prefix_label > ptr2->prefix_label)
return false;
ptr1 = &dp[ptr1->next_node];
ptr2 = &dp[ptr2->next_node];
} }
static inline ll sum(const std::vector<ll> &v){ return false;
ll res=0;
for(auto i:v){
res+=i;
}
return res;
} }
int main() { int main() {
std::iostream::sync_with_stdio(false); std::ios_base::sync_with_stdio(false);
std::cin.tie(nullptr); std::cin.tie(NULL);
// std::cout<<(std::vector<ll>({1,2,2})<std::vector<ll>({1,2,3}))<<"\n";
std::cin>>n>>m;
edg.resize(n+1);
ind.resize(n+1);
len.resize(n+1);
lv.resize(n+1);
for(ll i=1;i<=m;i++){ int n, m;
ll a,b,l; read(n);
std::cin>>b>>a>>l; read(m);
edg[a].emplace_back(b,l);
ind[b]++; std::vector<std::vector<Edge>> adj(n + 1);
std::vector<int> in_degree(n + 1, 0);
for (int i = 0; i < m; ++i) {
int u, v, l;
read(u);
read(v);
read(l);
adj[u].push_back({v, l});
in_degree[v]++;
} }
for(ll u=1;u<=n;u++){
if(ind[u]==0){ std::queue<int> q;
q.emplace(u); for (int i = 1; i <= n; ++i) {
if (in_degree[i] == 0) {
q.push(i);
} }
} }
while(q.size()){
ll top = q.front(); std::vector<int> topo_order;
topo_order.reserve(n);
while (!q.empty()) {
int u = q.front();
q.pop(); q.pop();
topo.emplace_back(top); topo_order.push_back(u);
for(auto [to,l]:edg[top]){
ind[to]--; for (const auto &edge : adj[u]) {
if(ind[to]==0){ int v = edge.to;
q.emplace(to); in_degree[v]--;
// len[to]=std::max(len[to],len[top]+1); if (in_degree[v] == 0) {
if(len[top]+1>len[to]){ q.push(v);
len[to]=len[top]+1;
lv[to] = lv[top];
lv[to].emplace_back(l);
}else if(len[to]==len[top]+1){
std::vector<ll> nlv = lv[top];
nlv.emplace_back(l);
if(lv[to]<nlv){
lv[to]=std::move(nlv);
} }
} }
} }
}
}
// p1v(topo);
// p1v(len);
for(ll i=1;i<=n;i++){
std::cout<<len[i]<<" "<<sum(lv[i])<<"\n";
}
std::vector<Path> dp(n + 1);
for (int i = n - 1; i >= 0; --i) {
int u = topo_order[i];
std::sort(adj[u].begin(), adj[u].end(), [](const Edge &a, const Edge &b) { return a.label < b.label; });
Path best_path = {};
for (const auto &edge : adj[u]) {
int v = edge.to;
int l = edge.label;
Path candidate_path;
candidate_path.len = 1 + dp[v].len;
candidate_path.sum = l + dp[v].sum;
candidate_path.prefix_label = l;
candidate_path.next_node = v;
if (is_better(candidate_path, best_path, dp)) {
best_path = candidate_path;
}
}
dp[u] = best_path;
}
for (int i = 1; i <= n; ++i) {
write(dp[i].len);
put_char(' ');
write(dp[i].sum);
put_char('\n');
}
return 0;
} }