说实话,这道题确乎让我挺无语的,不开__int128见祖宗,好的废话少说
Link
Solve
其实这道题的题意有那么一点不太明确,但是我们结合日常思维就可以想到是不会有环的,于是就开一个结构体记一下分数,刷一趟topo,但是比赛的时候对于数据大小的估算出了一些问题,导致数据爆炸,最稳的还是开高精,但是赛后发现__int128也能过,说明这个东西还是有一点用的,从2019T1,到CSPT2,再到这道题,CCF玩这种东西没什么意思,导致当场退役
Code
#include<bits/stdc++.h>
#define LL __int128
using namespace std;
const int maxn=100005,maxe=1000005;
LL gcd(LL m,LL n){while (n!=0){LL t=m%n;m=n;n=t;}return m;}
int N,M,Q[maxn],num[maxn];
int cnt,lnk[maxn],nxt[maxe],son[maxe],du[maxn];
inline void add_e(int x,int y){son[++cnt]=y;nxt[cnt]=lnk[x];lnk[x]=cnt;}
struct AS{
LL up,dn;
AS(){up=0;dn=1;}
void calc(){
LL G=gcd(up,dn);
if(G)up/=G,dn/=G;
}
AS operator +(const AS B){
AS ret;
ret.dn=dn*B.dn;
ret.up=up*B.dn+dn*B.up;
ret.calc();
return ret;
}
}A[maxn];
inline int read(){
int ret=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-f;ch=getchar();}
while(ch<='9'&&ch>='0')ret=ret*10+ch-'0',ch=getchar();
return ret*f;
}
inline void topo(){
int hed=0,til=0;
for(int i=1;i<=N;i++){
if(!du[i])Q[++til]=i;
}
while(hed<=til){
++hed;
if(A[Q[hed]].up!=0){
AS now=A[Q[hed]];now.dn*=num[Q[hed]];
for(int j=lnk[Q[hed]];j;j=nxt[j]){
A[son[j]]=A[son[j]]+now;
}
}
for(int j=lnk[Q[hed]];j;j=nxt[j]){
if(!--du[son[j]]){Q[++til]=son[j];}
}
}
return ;
}
void print(LL n) {
if(n > 9) print(n / 10);
putchar(n % 10 + 48);
}
int main(){
N=read();M=read();
for(int i=1;i<=N;i++){
num[i]=read();
for(int j=1;j<=num[i];j++){
int x=read();add_e(i,x);
du[x]++;
}
}
for(int i=1;i<=M;i++)A[i].up=1;
topo();
for(int i=1;i<=N;i++)if(!num[i]){
print(A[i].up);putchar(' ');print(A[i].dn);putchar('
');
}
return 0;
}