loj3386.「NOIP2020」排水系统
恶心的高精板子。
但 CCF 开了 C++14,于是真的变成送分题了。
直接拓扑排序就好了。
#include<iostream>
#include<cstdio>
#include<queue>
using namespace std;
#define int __int128
struct edge
{
int nxt,to;
}e[500001<<1];
int tot,h[100001],n,m,cnt,node[100001],d[100001],t[100001];
int a[100001],b[100001];
inline int read()
{
int x=0;
char c=getchar();
while(c<'0'||c>'9')
c=getchar();
while(c>='0'&&c<='9')
{
x=(x<<1)+(x<<3)+(c^48);
c=getchar();
}
return x;
}
inline void add(int x,int y)
{
e[++tot].nxt=h[x];
h[x]=tot;
e[tot].to=y;
}
long long gcd(int x,int y)
{
return x%y? gcd(y,x%y):y;
}
inline void insert(int x,int p,int q)
{
int g=gcd(b[x],q),h=b[x]/g*q;
a[x]=h/b[x]*a[x]+h/q*p;
b[x]=h;
g=gcd(a[x],b[x]);
a[x]/=g;
b[x]/=g;
}
inline void topo()
{
queue<int> Q;
for(register int i=1;i<=n;++i)
{
b[i]=1;
if(!d[i])
{
Q.push(i);
a[i]=1;
}
}
while(!Q.empty())
{
int k=Q.front();
Q.pop();
if(!t[k])
continue;
int p=a[k],q=b[k]*t[k];
int g=gcd(p,q);
p/=g;
q/=g;
for(register int i=h[k];i;i=e[i].nxt)
{
insert(e[i].to,p,q);
if(!--d[e[i].to])
Q.push(e[i].to);
}
}
}
void print(int x)
{
if(x>=10)
print(x/10);
putchar(x%10+'0');
}
signed main()
{
freopen("water.in","r",stdin);
freopen("water.out","w",stdout);
n=read(),m=read();
for(register int i=1;i<=n;++i)
{
t[i]=read();
if(!t[i])
node[++cnt]=i;
for(register int j=1;j<=t[i];++j)
{
int x=read();
add(i,x);
++d[x];
}
}
topo();
for(register int i=1;i<=cnt;++i)
{
print(a[node[i]]);
putchar(' ');
print(b[node[i]]);
putchar('\n');
}
return 0;
}