题解(含注释)
2026-01-04 21:36:52
发布于:广东
1阅读
0回复
0点赞
#include<bits/stdc++.h>
#define I128 __int128_t
using namespace std;
int n,m,cnt,head[100001],oud[100001],ind[100001];
I128 wx[100001],wy[100001];
queue<int>q; // 保存即将拓展的节点
struct node
{
int nxt,to;
}e[500001];
I128 gcd(I128 x,I128 y) // gcd 用来约分和实现加减
{
I128 t;
while(y)
{
t=y;
y=x%y;
x=t;
}
return x;
}
void add(int u,int v)
{
e[++cnt].nxt=head[u];
e[cnt].to=v;
head[u]=cnt;
}
void update(I128 &x_1,I128 &y_1,I128 x_2,I128 y_2) // 分数加减运算
{
I128 p=y_1*y_2/gcd(y_1,y_2);
x_1*=p/y_1;
x_2*=p/y_2;
x_1+=x_2;
y_1=p;
}
template<typename T>void read(T &x)
{
x=0;
char ch=getchar();
while(ch<'0'||ch>'9')ch=getchar();
while(ch>='0'&&ch<='9')
{
x=(x<<3)+(x<<1)+(ch^48);
ch=getchar();
}
}
void write(I128 x) // __int128_t 需要快读快写
{
if(x>9)write(x/10);
putchar(x%10+'0');
}
int main()
{
read(n),read(m);
for(register int i=1;i<=m;++i)
{
wx[i]=1;
q.push(i);
}
for(register int i=1,d;i<=n;++i)
{
read(d);
wy[i]=1; // 将分母都标记为 1,防止出错
oud[i]+=d;
for(register int j=1,x;j<=d;++j)
{
read(x);
add(i,x); // 增加一条从 i 到 x 的边
ind[x]++; // x 的入度加 1
}
}
while(q.size())
{
int u=q.front();
q.pop();
for(int i=head[u],v;i;i=e[i].nxt)
{
v=e[i].to;
update(wx[v],wy[v],wx[u],oud[u]*wy[u]);
ind[v]--; // 将入度减少 1
if(!ind[v])q.push(v);
}
}
for(register int i=1;i<=n;++i)
{
if(!oud[i])
{
I128 p=gcd(wx[i],wy[i]); // 约分操作
write(wx[i]/p);
putchar(' ');
write(wy[i]/p);
putchar('\n');
}
}
return 0;
}
这里空空如也







有帮助,赞一个