NOIP2020
T1:排水系统
题意:n 个排水节点(1 ... n),m 个接水口(1 ... m),0 个排水管道的为出水口。
输入样例:
5 1
3 2 3 5
2 4 5
2 5 4
0
0
输出样例:
1 3
2 3
画出样例数据当中的示意图,如下图所示:
1、确定入水口:根据题意可知,有m个入水口,那么具体的口是(1,2,... ,m)
2、确定出水口:根据题意可知,在输入数据当中,如果没有排出管道连到其他节点,那么即为出水口。根据输入为0的时候,用一个数组标记即可。
3、在模拟流到其他节点的时候,怎么恰当的表示数据?肯定不能每次都用小数算出来,这样会有数精度的损失。那么根据流出管道的数量size,只要每次乘以一个size,即可得分流到该节点的水流量。这时候分为两种情况:
1)假如是中间节点的话,那么只要不停的乘以这个size得到当前节点分母的大小,分子就一直都是1。然后加入队列。
2)如果是最终流出节点的话,那么就每次从队列里取出一个节点之后,若该节点的下一个节点就是流出节点的话,那么加上第一个流入该节点的流量;若后面还有节点流到该流出节点的话,那么就累加起来:得到最终的ans_x[i], ans_y[i]。两个分数相加的简单方法就是先用最大公约数求出最小公倍数,然后最小公倍数除以各自的分母即为两个分子要乘的积。加起来之后再用最大公约数约一下分得到最简分数。
因为本题的数据范围是:可能会到10-26,所以即使是long long也过不了。可以用double,然后对应的gcd改成 a - floor(a / b) * b即可。
AC代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 | #include <cstdio> #include <vector> #include <queue> #include <algorithm> #include <cmath> using namespace std; const int N = 1e5 + 10; const double eps = 1e-18; #define int long long int n, m; double x[N], y[N], G; struct Node{ int num, val; }b[N]; bool st[N]; vector< int > a[N]; queue<Node> q; double gcd( double a, double b) { if (a < b) swap(a, b); if (b < eps) return a; return gcd(b, a - floor (a / b) * b); } void bfs() { while (q.size()) { Node t = q.front(); q.pop(); int Size = ( int )a[t.num].size(); t.val *= Size; for ( int i = 0; i < Size; i ++) { int Y = a[t.num][i]; if (st[Y]) { if (!x[Y] || !y[Y]) { x[Y] = 1; y[Y] = t.val; continue ; } double g1 = gcd(y[Y], t.val), g = y[Y] / g1 * t.val; x[Y] = g / y[Y] * x[Y] + g / t.val * 1; y[Y] = g; G = gcd(x[Y], y[Y]); x[Y] /= G; y[Y] /= G; continue ; } q.push({Y, t.val}); } } } signed main() { scanf ( "%lld%lld" , &n, &m); for ( int i = 1; i <= n; i ++) { int T; scanf ( "%lld" , &T); if (!T) { st[i] = 1; continue ; } while (T --) { int x; scanf ( "%lld" , &x); a[i].push_back(x); } } for ( int i = 1; i <= m; i ++) { Node t; t.num = i; t.val = 1; q.push(t); } bfs(); for ( int i = 1; i <= n; i ++) if (st[i]) printf ( "%.0lf %.0lf\n" , x[i], y[i]); } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?