P7113 [NOIP2020] 排水系统 题解

题意

题面传送门

有一个图(DAG),n个节点,m个入度为0的点,每个入度为0的节点有一吨水,每个结点的水会平均地沿着边分给相邻的点,求每个出度为0的节点的水有多少。


前置芝士

  1. 拓扑排序
  2. 最大公因数
  3. 快写 / 高精度

思路

注意到这是一个DAG(有向无环图),我们可以使用拓扑排序,并在其过程中统计每个节点会收集到的水的重量。最终输出出度为0的节点的水的重量。


tips:

  1. 可以分别用两个数组存储每个节点水的重量分子和分母
计算分数加和的代码
void add(int v,int u){//将v的水的重量的出度分之一加入u的水的重量
	fz[v]=fz[v]*(fm[u]*out[u])/gcd(fm[v],fm[u]*out[u])+fz[u]*(fm[v])/gcd(fm[v],fm[u]*out[u]);
	fm[v]=fm[v]*fm[u]*out[u]/gcd(fm[v],fm[u]*out[u]);
}
void print(__int128 x){//__int128无法使用cout等,给__int128写快写
    if (!x) return ;
    if (x < 0) putchar('-'),x = -x;
    print(x / 10);
    putchar(x % 10 + '0');
}
  1. 观察数据范围,发现int和long long都存不下,但是可以使用__int128来存储分子和分母,__int128并不能用printf或cout输出,所以需要自己写一个快写。当然,你也可以选择写高精度。

代码

#include<bits/stdc++.h>
using namespace std;
const int MAXN=1e5+5;
const int MAXM=13;
int n,m;
int inb[MAXN];
__int128 out[MAXN];//记得开__int128或者写高精度哦
vector<int>vec[MAXN];
__int128 fm[MAXN],fz[MAXN];
queue<int> q;
__int128 gcd(__int128 a,__int128 b){//计算gcd(最大公约数)
	while(b){
		__int128 t=a%b;
		a=b,b=t;
	}
	return a;
}
void add(int v,int u){//将v的水的重量的出度分之一加入u的水的重量
	fz[v]=fz[v]*(fm[u]*out[u])/gcd(fm[v],fm[u]*out[u])+fz[u]*(fm[v])/gcd(fm[v],fm[u]*out[u]);
	fm[v]=fm[v]*fm[u]*out[u]/gcd(fm[v],fm[u]*out[u]);
}
void print(__int128 x){//__int128无法使用cout等,给__int128写快写
    if(!x) return ;
    if(x < 0) putchar('-'),x=-x;
    print(x/10);
    putchar(x%10+'0');
}
void sor(){//拓扑排序
	for(int i=1;i<=n;i++){
		if(inb[i]==0){
			fz[i]=1;
			q.push(i);
		}
	}
	while(!q.empty()){
		int u=q.front();
		q.pop();
		for(int i=0;i<vec[u].size();i++){
			int v=vec[u][i];
			add(v,u);//将v的水的重量的出度分之一加入u的水的重量
			inb[v]--;
			if(inb[v]==0){
				q.push(v);
			}
		}
	}
}
int main(){
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		int xx;
		cin>>xx;
		out[i]=xx;
		fm[i]=1;
		for(int j=1;j<=out[i];j++){
			int v;
			cin>>v;
			vec[i].push_back(v);
			inb[v]++;
		}
	}
	sor();
	for(int i=1;i<=n;i++){
		if(out[i]==0){
			__int128 G=gcd(fz[i],fm[i]);
			fz[i]/=G;
			fm[i]/=G;
			print(fz[i]);
			cout<<" ";
			print(fm[i]);
			cout<<endl;
		}
	}
}

结语

第一次写题解,有问题欢迎指出喵:D

作者:Le-Louvre

出处:https://www.cnblogs.com/Le-Louvre/p/18366450

版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。

posted @   卢浮宫  阅读(102)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
more_horiz
keyboard_arrow_up dark_mode palette
选择主题
点击右上角即可分享
微信分享提示