ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

NOIP2020

2021-10-02 20:04:36  阅读:234  来源: 互联网

标签:结点 int sum 污水 mom lll 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

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有