#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <algorithm>
using namespace std;
using ll=long long;
using ull = unsigned long long;
const int maxn=1e5,maxm=5e5;
int rd[maxn+100],d[maxn+100];
int n,m,hd[maxn+100],cnt(0),num;//num:排水口数量
//拓扑排序优化:用一个栈记录所有入度为0的节点,直接从stack里面取,不用每次遍历
int sk[maxn+100],top=0;
bool vis[maxn+10];
inline ull lgcd(ll a,ll b)
{
if(a==0||b==0) return 1;
return (a%b==0?b:lgcd(b,a%b));
}
struct EDGE {
int nxt,to;
} e[maxm+10];
class QT
{
public:
ull a,b;//a/b
QT() {}
QT(ull _a,ull _b):a(_a),b(_b) {}
inline void spf() {
if(a==0) return ;
ull p=lgcd(a,b);
a/=p,b/=p;
}
} w[maxn+100];
QT Div(QT nx,QT ny)//返回分数的商
{
QT res;
ull aa=nx.a,bb=nx.b;
ull cc=ny.a,dd=ny.b;
ull xa=lgcd(aa,cc),xb=lgcd(bb,dd);
aa/=xa,cc/=xa,bb/=xb,dd/=xb;
res.a=aa*dd,res.b=bb*cc;
return res;
}
QT Add(QT nx,QT ny)
{
//返回未化简的分数和
QT res;
ull aa=nx.a,bb=nx.b;
ull at=ny.a,bt=ny.b;
//通分
res.a=aa*bt+at*bb;
res.b=bb*bt;
return res;
}
ll Rd()
{
ll res(0),f(1);
char c=getchar();
while(!isdigit(c)) {
if(c=='-') f=-1;
c=getchar();
}
while(isdigit(c) ) {
res=(res<<1)+(res<<3)+(c^48);
c=getchar();
}
return res*f;
}
void AddEdge(int u,int v)
{
e[++cnt].to=v;
e[cnt].nxt=hd[u];
hd[u]=cnt;
}
int main()
{
// freopen("water2.in","r",stdin);
// freopen("water.out","w",stdout);
n=Rd(),m=Rd();
for(int i=1; i<=n; ++i) {
d[i]=Rd();
if(!d[i]) {
++num;//是一个排水口
continue;
}
int x;
for(int j=1; j<=d[i]; ++j) {
x=Rd();
AddEdge(i,x);
rd[x]++;
}
}
for(int i=1; i<=n; ++i) {
if(i<=m) {
w[i]=QT(1,1);
} else {
w[i]=QT(0,1);
}
}
int iLoc=-1;
for(int i=1; i<=n; ++i) {
if(!rd[i]&&d[i]) {
iLoc=i;
sk[++top]=i;
}
}
int ub=n-num;
for(int i=1; i<=ub; ++i) {
iLoc=sk[top--];
vis[iLoc]=true;//error1 :标记语句的位置
QT tmp=Div(w[iLoc],QT(d[iLoc],1));//error2:w[iLoc]才是节点的水量;d[iLoc]
tmp.spf();
for(int j=hd[iLoc]; j; j=e[j].nxt) {//起点:iLoc;终点:e[j].to;
rd[e[j].to]--;
if(!rd[e[j].to]&&d[e[j].to]) {
sk[++top]=e[j].to;//产生了入度0的节点
}
w[e[j].to]=Add(w[e[j].to],tmp);
w[e[j].to].spf();
}
w[iLoc]=QT(0,1);//清零当前结点
// for(int j=1; j<=n; ++j) {
// if(!rd[j]&&!vis[j]&&d[j]) {//error3:要注意排水口不能处理。有出度才处理
// iLoc=j;
// break;
// }
// }
// printf("处理第%d个点后:\n",iLoc);
// for(int i=1; i<=n; ++i) {
// if(w[i].a==0) {
// printf("0 ");
// continue ;
// }
// printf("%lld/%lld ",w[i].a,w[i].b);
// }
// printf("\n");
}
for(int i=1; i<=n; ++i) {
if(!vis[i]) {
printf("%lld %lld\n",w[i].a,w[i].b);
}
}
return 0;
}
第七个样例,输出22553173828125 440739022036306048
这样的数,和答案不一样?
请问哪里有问题?谢谢大佬指点!