NOIP2020
作者:互联网
P7113 NOIP2020排水系统
题目描述
对于一个城市来说,排水系统是极其重要的一个部分。
有一天,小 C 拿到了某座城市排水系统的设计图。排水系统由 n 个排水结点(它们从1∼n 编号)和若干个单向排水管道构成。每一个排水结点有若干个管道用于汇集其他排水结点的污水(简称为该结点的汇集管道),也有若干个管道向其他的排水结点排出污水(简称为该结点的排出管道)。
排水系统的结点中有 m个污水接收口,它们的编号分别为 1,2,3, m污水只能从这些接收口流入排水系统,并且这些结点没有汇集管道。排水系统中还有若干个最终排水口,它们将污水运送到污水处理厂,没有排出管道的结点便可视为一个最终排水口。
现在各个污水接收口分别都接收了1 吨污水,污水进入每个结点后,会均等地从当前结点的每一个排出管道流向其他排水结点,而最终排水口将把污水排出系统。
现在小 C 想知道,在该城市的排水系统中,每个最终排水口会排出多少污水。该城市的排水系统设计科学,管道不会形成回路,即不会发生污水形成环流的情况。
输入格式
第一个两个用单个空格分隔的整数 n,m。分别表示排水结点数与接收口数量。
接下来 n行,第 i 行用于描述结点 i 的所有排出管道。其中每行第一个整数
表示其排出管道的数量,接下来个用单个空格分隔的整数依次表示管道的目标排水结点。
保证不会出现两条起始结点与目标结点均相同的管道。
输出格式
输出若干行,按照编号从小到大的顺序,给出每个最终排水口排出的污水体积。其中体积使用分数形式进行输出,即每行输出两个用单个空格分隔的整数 p,q,表示排出的污水体积为p / q。要求 p 与 q 互素,q = 1 时也需要输出 q。
输入 #1
5 1
3 2 3 5
2 4 5
2 5 4
0
0
输出 #1
1 3
2 3
输入 #2
10 1
5 2 3 4 5 6
2 7 8
2 8 10
2 9 7
1 9
3 7 8 9
1 10
0
1 10
0
输出 #2
4 15
11 15
分析
保证不会出现两条起始结点与目标结点均相同的管道。这表明了这是一个裸的拓扑排序,需要注意的是用分数表示,分数要约分到最简,还有这毒瘤的数据。
unsigned long long 也过不了,会WA一个点,需要用__int128.
注意printf和cout 都无法输出__int 128的数据,需要用字符形式输出。
代码
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <queue>
#include <cstring>
#define lll __int128
using namespace std;
const int N=2e7;
lll gcd(lll a,lll b)
{
if(b == 0) return a;
return gcd(b,a%b);
}
struct edge{
int from;
int to;
int dis;
int next;
}e[N];
int head[N],cnt;
void add(int u,int v)
{
++cnt;
e[cnt].from = u;
e[cnt].to = v;
e[cnt].next = head[u];
head[u] = cnt;
}
struct node{
lll son;
lll mom;
node()
{
lll son = 0;
lll mom = 0;
}
}ans[N];
node check(node a,node b)
{
node sum;
if(a.son == 0 && a.mom == 0)
{
sum.son = b.son;
sum.mom = b.mom;
return sum;
}
lll p = a.mom/gcd(a.mom,b.mom)*b.mom;
sum.mom = p;
sum.son = (p/a.mom*a.son)+(p/b.mom*b.son);
lll t = gcd(sum.son,sum.mom);
sum.son /= t;
sum.mom /= t;
return sum;
}
int n,m;
int x;
int num[N];
int ru[N],chu[N];
queue<int> q;
void print(lll n) {
if(n > 9) print(n / 10);
putchar(n % 10 + 48);
//n % 10+'0'(48)表示字符0~9
//putchar输出的是字符。
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
{
cin>>num[i];
for(int j=1;j<=num[i];j++)
{
cin>>x;
add(i,x);
ru[x]++;
chu[i]++;
}
}
for(int i=1;i<=n;i++)
if(ru[i] == 0)
{
q.push(i);
ans[i].son = 1;
ans[i].mom = 1;
}
while(!q.empty())
{
int x = q.front();
if(num[x] != 0) ans[x].mom *= num[x];
q.pop();
for(int i=head[x];i;i=e[i].next)
{
int y = e[i].to;
ans[y] = check(ans[y],ans[x]);
ru[y]--;
if(ru[y] == 0) q.push(y);
//cout<<y<<" "<<ans[y].son<<" "<<ans[y].mom<<endl;
}
}
for(int i=1;i<=n;i++)
{
if(chu[i] == 0)
{
lll w = gcd(ans[i].son,ans[i].mom);
ans[i].mom /= w;//再约分一次保证互质
ans[i].son /= w;
print(ans[i].son);
printf(" ");
print(ans[i].mom);
printf("\n");
}
}
return 0;
}
标签:结点,int,sum,污水,mom,lll,NOIP2020 来源: https://www.cnblogs.com/Elgina/p/15362511.html