题解:[NOIP2020] 排水系统

题目传送门

题意分析

“不会发生污水形成环流的情况”,即无环,则整张图为一张有向无环图。

那么很容易想到拓扑排序,拓扑排序后统计贡献即可。

这道题目的难度可能就在于分数运算,但是也不难,写个结构体用 __int128 实现即可。

AC 代码

时间复杂度:\(\mathcal O(n\log V)\)。其中 \(\mathcal O(\log V)\) 是求解最大公因数带来的。

//#include<bits/stdc++.h>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<iomanip>
#include<cstdio>
#include<string>
#include<vector>
#include<cmath>
#include<ctime>
#include<deque>
#include<queue>
#include<stack>
#include<list>
using namespace std;
typedef unsigned __int128 ll;
constexpr const int N=1e5,M=10,D=5;
//正分数 
ll gcd(ll a,ll b){
	while(b){
		ll tmp=b;
		b=a%b;
		a=tmp;
	}
	return a;
}
ll lcm(ll a,ll b){
	return a/gcd(a,b)*b;
}
struct frac{
	ll p,q;
	frac(){
		q=1,p=0;
	}
	frac(ll x){
		q=1,p=x;
	}
	frac(ll pp,ll qq){
		p=pp,q=qq;
	}
};
frac operator +(frac a,frac b){
	frac c;
	c.q=lcm(a.q,b.q);
	c.p=a.p*c.q/a.q+b.p*c.q/b.q;
	ll pl=gcd(c.p,c.q);
	c.p/=pl;
	c.q/=pl;
	return c;
}
frac operator +=(frac &a,frac b){
	return a=a+b;
}
frac operator /(frac a,ll b){
	a.q*=b;
	ll pl=gcd(a.p,a.q);
	a.p/=pl;
	a.q/=pl;
	return a;
}
int n,m;
struct node{
	int d;
	int a[D+1];
	frac value;
}a[N+1];
void topSort(){
	static int in[N+1];
	for(int i=1;i<=n;i++){
		for(int j=1;j<=a[i].d;j++){
			in[a[i].a[j]]++;
		}
	}
	queue<int>q;
	for(int i=1;i<=n;i++){
		if(!in[i]){
			q.push(i);
		}
	}
	while(q.size()){
		int x=q.front();q.pop();
		frac add=a[x].value/a[x].d;
		for(int i=1;i<=a[x].d;i++){
			a[a[x].a[i]].value+=add;
			if(--in[a[x].a[i]]==0){
				q.push(a[x].a[i]);
			}
		}
	}
}
void Write(ll x){
	static char s[101]={};
	int top=0;
	do{
		s[++top]=x%10^'0';
		x/=10;
	}while(x);
	while(top){
		cout<<s[top--];
	}
}
int main(){
	/*freopen("test.in","r",stdin);
	freopen("test.out","w",stdout);*/
	
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		cin>>a[i].d;
		for(int j=1;j<=a[i].d;j++){
			cin>>a[i].a[j];
		}
	}
	for(int i=1;i<=m;i++){
		a[i].value=1;
	}
	topSort();
	for(int i=1;i<=n;i++){
		if(!a[i].d){
			Write(a[i].value.p);
			cout<<' ';
			Write(a[i].value.q);
			cout<<'\n';
		}
	}
	
	/*fclose(stdin);
	fclose(stdout);*/
	return 0;
}
posted @ 2025-07-21 21:45  TH911  阅读(6)  评论(0)    收藏  举报