60pts求助
查看原帖
60pts求助
363491
U_92_Uranium楼主2022/11/17 09:02
#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

这样的数,和答案不一样?

请问哪里有问题?谢谢大佬指点!

2022/11/17 09:02
加载中...