//https://img2018.cnblogs.com/blog/1646268/201908/1646268-20190806114008215-138720377.jpg

NOIP2020 排水系统

只能说对于分数的处理很麻烦,其他的都好做。

读完题不难发现流水的过程很像拓扑排序的过程,当然你要说网络流也行

直接暴力一直扩大分母的话会爆,需要在除法加法的时候不断化简才行,所以很麻烦,这里用结构体存分子分母,写了两个函数实现。

然后就是按照入度拓扑排序,入度为零的肯定不会再有水流进去,所以是已经确定的,另外对于没有出度的点要跳过,避免除以 \(0\) 出问题。

实在想不出来咋讲,感觉就是实现困难

/*
 * @Author: Aisaka_Taiga
 * @Date: 2023-10-28 14:39:38
 * @LastEditTime: 2023-10-28 15:38:56
 * @LastEditors: Aisaka_Taiga
 * @FilePath: \Desktop\P7113.cpp
 * The heart is higher than the sky, and life is thinner than paper.
 */
#include <bits/stdc++.h>

// #define int long long
#define int __int128
#define N 100010

using namespace std;

inline int read(){int x = 0, f = 1;char c = getchar();while(c < '0' || c > '9'){if(c == '-') f = -1; c = getchar();}while(c <= '9' && c >= '0') x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();return x * f;}

inline void print(int n){if(n > 9) print(n / 10); putchar(n % 10 + 48);}

int n, m, du[N], v[N];
vector<int> g[N];
struct node{int fz, fm;}e[N];

inline node chu(node a, int x)
{
    a.fm *= x;
    int gcd = __gcd(a.fz, a.fm);
    // cout << "gcd : " << gcd << endl;
    a.fz /= gcd;
    a.fm /= gcd;
    return a;
}

inline node jia(node a, node b)
{
    node c;
    if(a.fz == 0 && a.fm == 0) return b;
    int gcd = __gcd(a.fm, b.fm);
    int c1 = b.fm / gcd;
    int c2 = a.fm / gcd;
    c.fm = a.fm * b.fm / gcd;
    c.fz = (a.fz * c1 + b.fz * c2);
    return c;
}

inline node huajian(node a)
{
    int gcd = __gcd(a.fm, a.fz);
    a.fm /= gcd;
    a.fz /= gcd;
    return a;
}

inline void topo()
{
    queue<int> q;
    for(int i = 1; i <= n; i ++)
    {
        if(du[i] != 0) continue;
        q.push(i);
        e[i].fz = e[i].fm = 1;
    }
    while(!q.empty())
    {
        int u = q.front();
        q.pop();
        if(v[u] == 0) continue;
        node c = chu(e[u], v[u]);
        // cout << " U : " << u << endl;
        for(auto v : g[u])
        {
            e[v] = jia(e[v], c);
            du[v] --;
            if(du[v] == 0) q.push(v);
        }
    }
    return ;
}

signed main()
{
    n = read(), m = read();
    for(int i = 1; i <= n; i ++)
    {
        v[i] = read();
        for(int j = 1; j <= v[i]; j ++)
        {
            int x = read();
            g[i].emplace_back(x);
            du[x] ++;
        }
    }
    topo();
    for(int i = 1; i <= n; i ++)
    {
        if(v[i] == 0)
        {
            e[i] = huajian(e[i]);
            // cout << e[i].fz << " " << e[i].fm << endl;
            print(e[i].fz);
            cout << " ";
            print(e[i].fm);
            cout << endl;
        }
    }
    return 0;
}
posted @ 2023-10-28 15:40  北烛青澜  阅读(2)  评论(0编辑  收藏  举报