loj3386.「NOIP2020」排水系统

题目链接

恶心的高精板子。

但 CCF 开了 C++14,于是真的变成送分题了qq_emoji: cy

直接拓扑排序就好了。

#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;
}
posted @ 2021-09-23 16:46  绝顶我为峰  阅读(86)  评论(0编辑  收藏  举报