NC214837. [NOIP2020]排水系统(water)
描述
输入描述
第一行两个用单空格分隔的整数 n,m。分别表示排水结点数与接收口数量。接下来 n 行,第 i 行用于描述结点 i 的所有排出管道。其中每行第一个整数 di 表示其排出管道的数量,接下来 di 个用单个空格分隔的整数 a1,a2,…,adi 依次表示管道的目标排水结点。保证不会出现两条起始结点与目标结点均相同的管道。
输出描述
输出若干行,按照编号从小到大的顺序,给出每个最终排水口排出的污水体积。其中体积使用分数的形式进行输出,即每行输出两个用单个空格分隔的整数 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 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
输出:
4 15 11 15
C++(g++ 7.5.0) 解法, 执行用时: 203ms, 内存消耗: 9200K, 提交时间: 2023-08-03 17:57:15
#include<bits/stdc++.h> using namespace std; const int N=1e5+5; int n,m,x,k[N]; long double p[N],q[N]; vector<int> a[N]; long double gcd(long double x,long double y){ return y==0?x:gcd(y,x-(long long)(x/y)*y); } void to(long double x,long double y,long double &xx,long double &yy){ long double kk=gcd(y,yy); y/=kk,yy/=kk; x*=yy,xx*=y; yy*=kk*y; xx+=x; long double k=gcd(xx,yy); xx/=k,yy/=k; } void dfs(int x){ for(auto y:a[x]){ to(p[x],q[x]*k[x],p[y],q[y]); dfs(y); } if(k[x]) p[x]=0,q[x]=1; } int main(){ cin>>n>>m; for(int i=1;i<=n;i++){ scanf("%d",k+i),q[i]=1; for(int j=1;j<=k[i];j++) scanf("%d",&x),a[i].push_back(x); } for(int i=1;i<=m;i++){ p[i]=1; dfs(i); } for(int i=1;i<=n;i++) if(!k[i]) printf("%.0Lf %.0Lf\n",p[i],q[i]); }
C++(clang++ 11.0.1) 解法, 执行用时: 241ms, 内存消耗: 35764K, 提交时间: 2022-11-27 09:36:58
#include<bits/stdc++.h> #define ld long double #define ll long long #define N 1234567 using namespace std; ld p[N],q[N]; vector<int>a[N]; int n,m,x,k[N]; ld gcd(ld x,ld y){return y==0?x:gcd(y,x-(ll)(x/y)*y);} void to(ld x,ld y,ld &xx,ld &yy){ld kk=gcd(y,yy);y/=kk,yy/=kk,x*=yy,xx*=y,yy*=kk*y,xx+=x;ld k=gcd(xx,yy);xx/=k,yy/=k;} void dfs(int x){ for(auto y:a[x]){to(p[x],q[x]*k[x],p[y],q[y]);dfs(y);} if(k[x]) p[x]=0,q[x]=1; } int main(){ cin>>n>>m; for(int i=1;i<=n;i++){ cin>>k[i],q[i]=1; for(int j=1;j<=k[i];j++)cin>>x,a[i].push_back(x); }for(int i=1;i<=m;i++)p[i]=1,dfs(i); for(int i=1;i<=n;i++)if(!k[i])printf("%.0Lf %.0Lf\n",p[i],q[i]); }