5 条题解
-
2
解答
这题用分数?不可能的!!!
因为我整天被分数创,所以我想尽办法把分数规避掉。
因为过程上最多经过 个节点(算上开头和结尾),我们另一个把初始流量从 改成 ,这样全程都不会出现分数。
然后进行拓扑排序就行了。
最后答案就是 。
注意:请使用
__int128,否则保龄。code
#include<bits/stdc++.h> using namespace std; const int N = 1e5+10; struct node { __int128 p; }; __int128 qpow(__int128 a,__int128 b) { __int128 c=1; for(int i=1;i<=b;i++) c*=a; return c; } void out(__int128 x) { if(x==0) cout<<0; stack<int> st; while(st.size()) st.pop(); while(x) { st.push(int(x%10)); x/=10; } while(st.size()) cout<<st.top(),st.pop(); } int n,m; queue<int> q; vector<int> ed; __int128 w[N]; int d[N]; vector<int> e[N]; __int128 tmp=qpow(60,12); __int128 gcd(__int128 a,__int128 b) { if(b==0) return a; else return gcd(b,a%b); } int rudu[N]; int main() { cin>>n>>m; for(int i=1;i<=n;i++) { cin>>d[i]; for(int j=1;j<=d[i];j++) { int v; cin>>v; e[i].push_back(v);rudu[v]++; } if(d[i]==0) ed.push_back(i); } for(int i=1;i<=n;i++) { if(rudu[i]==0) { q.push(i); w[i]=tmp; } } while(q.size()) { int u=q.front(); q.pop(); __int128 dd=d[u]; for(auto v:e[u]) { rudu[v]--; w[v]+=w[u]/dd; if(rudu[v]==0) q.push(v); } } for(auto i:ed) { __int128 q=tmp,p=w[i]; __int128 res=gcd(q,p); q/=res;p/=res; out(p);cout<<' ';out(q);cout<<'\n'; } return 0; } -
1
給定的圖是一個DAG,所以顯然使用拓撲排序
每次對於一個入度為 的點 ,假設該點會流入 大小的水,那給所有 可以到達的點 ,向其中加入 的水
然後就是考慮分數的問題,顯然有:
$$\frac{x}{y} \times \frac{1}{z} = \frac{\frac{x}{\gcd(x,z)}}{y\times \frac{z}{\gcd(x,z)}} $$$$\frac{x}{y} + \frac{a}{b} = \frac{x\times b + a\times y}{y\times b} $$注意不要使用
long long要改成__int128#include<iostream> #include<cstdio> #include<queue> #define int __int128 using namespace std; bool Test_MLE_start; const int N=1e5+10; int _=1,n,m,tot=0,head[N],ind[N],oud[N],fm[N],fz[N]; struct edge{int v,nxt;}a[N<<1]; queue<int> q; inline int reads(){ char c=getchar(); int x=0,f=1; while(!isdigit(c)){if(c=='-') f=-1;c=getchar();} while(isdigit(c)){x=(x<<3)+(x<<1)+(c^'0');c=getchar();} return x*f; } void writes(int x){ if(x>9) writes(x/10); putchar(x%10+'0'); } inline void files(){ freopen("water.in","r",stdin); freopen("water.out","w",stdout); } inline void clr(){ // Don't forget! } void add(int u,int v){ a[++tot].v=v,ind[v]++,oud[u]++; a[tot].nxt=head[u]; head[u]=tot; } int gcd(int n,int m){return m?gcd(m,n%m):n;} void solve(int &fz1,int &fm1,int fz2,int fm2){ if(!fz1&&!fm1) fz1=fz2,fm1=fm2; else{ int GCD=gcd(fm1*fm2,fz1*fm2+fz2*fm1); fz1=(fz1*fm2+fz2*fm1)/GCD,fm1=fm1*fm2/GCD; } } bool Test_MLE_end; signed main(){// LL ¼«¶ËÊý¾Ý // printf("%lf Mb\n",(&Test_MLE_end-&Test_MLE_start-1)/1024.0/1024.0); // files(); // _=reads(); while(_--){ clr();n=reads(),m=reads(); for(int i=1;i<=n;i++){ int k;k=reads(); while(k--){ int v;v=reads(); add(i,v); } } for(int i=1;i<=n;i++){ if(!ind[i]) fz[i]=fm[i]=1,q.push(i); } while(!q.empty()){ int u=q.front();q.pop(); for(int i=head[u];i;i=a[i].nxt){ int v=a[i].v,GCD=gcd(fz[u],oud[u]); int adfz=fz[u]/GCD,adfm=oud[u]/GCD*fm[u]; solve(fz[v],fm[v],adfz,adfm); if(!(--ind[v])) q.push(v); } } for(int i=1;i<=n;i++){ if(!oud[i]) writes(fz[i]),printf(" "),writes(fm[i]),printf("\n"); } } return 0; } -
1
给定的图是一个DAG,所以显然使用拓扑排序
每次对于一个入度为 的点 ,假设该点会流入 大小的水,那给所有 可以到达的点 ,向其中加入 的水
然后就是考虑分数的问题,显然有:
$$\frac{x}{y} \times \frac{1}{z} = \frac{\frac{x}{\gcd(x,z)}}{y\times \frac{z}{\gcd(x,z)}} $$$$\frac{x}{y} + \frac{a}{b} = \frac{x\times b + a\times y}{y\times b} $$注意不要使用
long long要改成__int128#include<iostream> #include<cstdio> #include<queue> #define int __int128 using namespace std; bool Test_MLE_start; const int N=1e5+10; int _=1,n,m,tot=0,head[N],ind[N],oud[N],fm[N],fz[N]; struct edge{int v,nxt;}a[N<<1]; queue<int> q; inline int reads(){ char c=getchar(); int x=0,f=1; while(!isdigit(c)){if(c=='-') f=-1;c=getchar();} while(isdigit(c)){x=(x<<3)+(x<<1)+(c^'0');c=getchar();} return x*f; } void writes(int x){ if(x>9) writes(x/10); putchar(x%10+'0'); } inline void files(){ freopen("water.in","r",stdin); freopen("water.out","w",stdout); } inline void clr(){ // Don't forget! } void add(int u,int v){ a[++tot].v=v,ind[v]++,oud[u]++; a[tot].nxt=head[u]; head[u]=tot; } int gcd(int n,int m){return m?gcd(m,n%m):n;} void solve(int &fz1,int &fm1,int fz2,int fm2){ if(!fz1&&!fm1) fz1=fz2,fm1=fm2; else{ int GCD=gcd(fm1*fm2,fz1*fm2+fz2*fm1); fz1=(fz1*fm2+fz2*fm1)/GCD,fm1=fm1*fm2/GCD; } } bool Test_MLE_end; signed main(){// LL ¼«¶ËÊý¾Ý // printf("%lf Mb\n",(&Test_MLE_end-&Test_MLE_start-1)/1024.0/1024.0); // files(); // _=reads(); while(_--){ clr();n=reads(),m=reads(); for(int i=1;i<=n;i++){ int k;k=reads(); while(k--){ int v;v=reads(); add(i,v); } } for(int i=1;i<=n;i++){ if(!ind[i]) fz[i]=fm[i]=1,q.push(i); } while(!q.empty()){ int u=q.front();q.pop(); for(int i=head[u];i;i=a[i].nxt){ int v=a[i].v,GCD=gcd(fz[u],oud[u]); int adfz=fz[u]/GCD,adfm=oud[u]/GCD*fm[u]; solve(fz[v],fm[v],adfz,adfm); if(!(--ind[v])) q.push(v); } } for(int i=1;i<=n;i++){ if(!oud[i]) writes(fz[i]),printf(" "),writes(fm[i]),printf("\n"); } } return 0; } -
-1
按照题意模拟即可。
通分的时候可能会爆
long long,所以改成long double或__int128。#include<bits/stdc++.h> #define R(x) x=read() #define int __int128 using namespace std; inline int read() { int x=0,y=1; char c=getchar(); while(c<'0'||c>'9') { if(c=='-') y=-1; c=getchar(); } while(c>='0'&&c<='9') { x=(x<<3)+(x<<1)+(c^'0'); c=getchar(); } return x*y; } void write(int x){ if(x>9)write(x/10); putchar(x%10+'0'); } const int N=200005; int gcd(int x,int y) { if(y==0)return x; return gcd(y,x%y); } int n,m; int a[N],b[N]; int d[N]; int ans[N],tot; vector<int>G[N]; queue<int>q; int ind[N]; signed main() { freopen("water.in","r",stdin); freopen("water.out","w",stdout); R(n),R(m); for(int i=1,x; i<=n; ++i) { R(d[i]); for(int j=1;j<=d[i];++j) { R(x); G[i].push_back(x); ++ind[x]; } if(!d[i])ans[++tot]=i; } for(int i=1; i<=n; ++i) { b[i]=1; if(!ind[i]) { a[i]=1; q.push(i); } } while(!q.empty()) { int u=q.front(); q.pop(); for(auto v:G[u]){ int av=a[v],bv=b[v]; a[v]=av*b[u]*d[u]+bv*a[u]; b[v]=bv*b[u]*d[u]; int g=gcd(a[v],b[v]); a[v]/=g,b[v]/=g; if(!(--ind[v]))q.push(v); } } for(int i=1;i<=tot;++i){ write(a[ans[i]]),putchar(' '),write(b[ans[i]]),putchar('\n'); } return 0; } -
-2
The given graph is a DAG, so it is obvious to use topological sorting
For each point with a degree of , assuming that the point will flow with water of size, add water of to all points that can reach
Then there is the issue of considering scores, which obviously includes:
$$\frac{x}{y} \times \frac{1}{z} = \frac{\frac{x}{\gcd(x,z)}}{y\times \frac{z}{\gcd(x,z)}} $$$$\frac{x}{y} + \frac{a}{b} = \frac{x\times b + a\times y}{y\times b} $$Be careful not to use
long longinstead of__int128#include<iostream> #include<cstdio> #include<queue> #define int __int128 using namespace std; bool Test_MLE_start; const int N=1e5+10; int _=1,n,m,tot=0,head[N],ind[N],oud[N],fm[N],fz[N]; struct edge{int v,nxt;}a[N<<1]; queue<int> q; inline int reads(){ char c=getchar(); int x=0,f=1; while(!isdigit(c)){if(c=='-') f=-1;c=getchar();} while(isdigit(c)){x=(x<<3)+(x<<1)+(c^'0');c=getchar();} return x*f; } void writes(int x){ if(x>9) writes(x/10); putchar(x%10+'0'); } inline void files(){ freopen("water.in","r",stdin); freopen("water.out","w",stdout); } inline void clr(){ // Don't forget! } void add(int u,int v){ a[++tot].v=v,ind[v]++,oud[u]++; a[tot].nxt=head[u]; head[u]=tot; } int gcd(int n,int m){return m?gcd(m,n%m):n;} void solve(int &fz1,int &fm1,int fz2,int fm2){ if(!fz1&&!fm1) fz1=fz2,fm1=fm2; else{ int GCD=gcd(fm1*fm2,fz1*fm2+fz2*fm1); fz1=(fz1*fm2+fz2*fm1)/GCD,fm1=fm1*fm2/GCD; } } bool Test_MLE_end; signed main(){// LL ¼«¶ËÊý¾Ý // printf("%lf Mb\n",(&Test_MLE_end-&Test_MLE_start-1)/1024.0/1024.0); // files(); // _=reads(); while(_--){ clr();n=reads(),m=reads(); for(int i=1;i<=n;i++){ int k;k=reads(); while(k--){ int v;v=reads(); add(i,v); } } for(int i=1;i<=n;i++){ if(!ind[i]) fz[i]=fm[i]=1,q.push(i); } while(!q.empty()){ int u=q.front();q.pop(); for(int i=head[u];i;i=a[i].nxt){ int v=a[i].v,GCD=gcd(fz[u],oud[u]); int adfz=fz[u]/GCD,adfm=oud[u]/GCD*fm[u]; solve(fz[v],fm[v],adfz,adfm); if(!(--ind[v])) q.push(v); } } for(int i=1;i<=n;i++){ if(!oud[i]) writes(fz[i]),printf(" "),writes(fm[i]),printf("\n"); } } return 0; }
- 1
信息
- ID
- 466
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 9
- 标签
- (无)
- 递交数
- 8
- 已通过
- 6
- 上传者