mirror of
https://gitcode.com/Zengtudor/alg2025.git
synced 2025-09-12 02:50:01 +00:00
perf(P9981): 优化图算法性能并实现快速IO
重构图遍历算法,使用更高效的数据结构和比较逻辑 添加FastIO模块提升输入输出性能
This commit is contained in:
parent
88b393ac28
commit
8c8fc92b3b
@ -1,107 +1,196 @@
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <iostream>
|
||||
#include <istream>
|
||||
#include <queue>
|
||||
#include <tuple>
|
||||
#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;
|
||||
|
||||
struct Edge{
|
||||
ll to,l;
|
||||
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 {
|
||||
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{\
|
||||
std::cout<<#ind<<"\n";\
|
||||
for(auto& i:ind){\
|
||||
std::cout<<i<<", ";\
|
||||
}\
|
||||
std::cout<<"\n";\
|
||||
}while(0)
|
||||
struct Path {
|
||||
long long len = 0;
|
||||
long long sum = 0;
|
||||
int prefix_label = 0;
|
||||
int next_node = 0;
|
||||
};
|
||||
|
||||
namespace std{
|
||||
static inline bool operator<(const vector<ll>&a,const vector<ll>&b){
|
||||
if((a.size()|b.size()) == 0){
|
||||
return false;
|
||||
}
|
||||
if(a.size()==0 && b.size()!=0){
|
||||
bool is_better(const Path &p_cand, const Path &p_best, const std::vector<Path> &dp) {
|
||||
if (p_cand.len > p_best.len)
|
||||
return true;
|
||||
if (p_cand.len < p_best.len)
|
||||
return false;
|
||||
|
||||
if (p_cand.len == 0)
|
||||
return false;
|
||||
|
||||
if (p_cand.prefix_label < p_best.prefix_label)
|
||||
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(a.size()!=0 && b.size() == 0){
|
||||
if (ptr1->prefix_label > ptr2->prefix_label)
|
||||
return false;
|
||||
}
|
||||
for(ll i=0;i<a.size()&&i<b.size()&&i<500;i++){
|
||||
if(a[i]<b[i])return true;
|
||||
else if(a[i]>b[i])return false;
|
||||
}
|
||||
return a.size()<b.size();
|
||||
ptr1 = &dp[ptr1->next_node];
|
||||
ptr2 = &dp[ptr2->next_node];
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline ll sum(const std::vector<ll> &v){
|
||||
ll res=0;
|
||||
for(auto i:v){
|
||||
res+=i;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
int main() {
|
||||
std::ios_base::sync_with_stdio(false);
|
||||
std::cin.tie(NULL);
|
||||
|
||||
int main(){
|
||||
std::iostream::sync_with_stdio(false);
|
||||
std::cin.tie(nullptr);
|
||||
// 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);
|
||||
int n, m;
|
||||
read(n);
|
||||
read(m);
|
||||
|
||||
for(ll i=1;i<=m;i++){
|
||||
ll a,b,l;
|
||||
std::cin>>b>>a>>l;
|
||||
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){
|
||||
q.emplace(u);
|
||||
|
||||
std::queue<int> q;
|
||||
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();
|
||||
topo.emplace_back(top);
|
||||
for(auto [to,l]:edg[top]){
|
||||
ind[to]--;
|
||||
if(ind[to]==0){
|
||||
q.emplace(to);
|
||||
// len[to]=std::max(len[to],len[top]+1);
|
||||
if(len[top]+1>len[to]){
|
||||
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);
|
||||
}
|
||||
}
|
||||
topo_order.push_back(u);
|
||||
|
||||
for (const auto &edge : adj[u]) {
|
||||
int v = edge.to;
|
||||
in_degree[v]--;
|
||||
if (in_degree[v] == 0) {
|
||||
q.push(v);
|
||||
}
|
||||
}
|
||||
}
|
||||
// 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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user