这个题开始正向拓扑排序,然后各种wa,心灰意冷,找了个题解,和同学研究了半天,甚至曾经一度认为题解是错的。
这个题正向反向应该都无所谓,但是我实在是蒻,打了半天正向都没打过去,最后跟随dalao的步伐走向了反向拓扑
#include<iostream> #include<cstring> #include<cstdio> #include<queue> #include<stack> using namespace std; int n,m,x,y,z,head[100010],tail,ru[100010],chu[100010]; bool flag[100010]; double ans[100010]; queue<int>qwq; struct in {int to,ne,co; }ter[200020]; inline void build(int f,int l,int c) {ter[++tail]=(in){l,head[f],c},head[f]=tail; } int main() {memset(head,-1,sizeof(head));scanf("%d%d",&n,&m);for(int i=1;i<=m;i++)scanf("%d%d%d",&x,&y,&z),build(y,x,z),ru[x]++,chu[x]++;//反向建图,因为从1跑不到的点肯定反向建图也跑不到1 for(int i=1;i<=n;i++)if(!ru[i])//如果原图该点,没有出边(终点) qwq.push(i);while(!qwq.empty()){int qaq=qwq.front();qwq.pop();//这里可以换成栈,跑的还更快,虽然我不知道为啥 for(int i=head[qaq];i>0;i=ter[i].ne){int t=ter[i].to;double gai=1.0/chu[t];ans[t]+=(ans[qaq]+ter[i].co)*gai;//求期望的必要步骤嘛qwq ru[t]--;if(!ru[t])qwq.push(t);} }for(int i=1;i<=n;i++)printf("%.2lf ",ans[i]);//printf("%.2lf",ans[1]); } /*关于这个反向拓扑排序可以的原因 因为每一个点都可以到达终点,所以无论正向反向,所有的从1到n的路径的期望值都不会变 所以正向反向无所谓 为什么要用拓扑排序 因为只有一个点所有到他的边都被走过,关于到它的期望值才算真正确定 */ #include<iostream> #include<cstring> #include<cstdio> #include<queue> #include<stack> using namespace std; int n,m,x,y,z,head[100010],tail,ru[100010],chu[100010]; bool flag[100010]; double ans[100010]; queue<int>qwq; struct in {int to,ne,co; }ter[200020]; inline void build(int f,int l,int c) {ter[++tail]=(in){l,head[f],c},head[f]=tail; } int main() {memset(head,-1,sizeof(head));scanf("%d%d",&n,&m);for(int i=1;i<=m;i++)scanf("%d%d%d",&x,&y,&z),build(y,x,z),ru[x]++,chu[x]++;//反向建图,因为从1跑不到的点肯定反向建图也跑不到1 for(int i=1;i<=n;i++)if(!ru[i])//如果原图该点,没有出边(终点) qwq.push(i);while(!qwq.empty()){int qaq=qwq.front();qwq.pop();//这里可以换成栈,跑的还更快,虽然我不知道为啥 for(int i=head[qaq];i>0;i=ter[i].ne){int t=ter[i].to;double gai=1.0/chu[t];ans[t]+=(ans[qaq]+ter[i].co)*gai;//求期望的必要步骤嘛qwq ru[t]--;if(!ru[t])qwq.push(t);} }for(int i=1;i<=n;i++)printf("%.2lf ",ans[i]);//printf("%.2lf",ans[1]); } /*关于这个反向拓扑排序可以的原因 因为每一个点都可以到达终点,所以无论正向反向,所有的从1到n的路径的期望值都不会变 所以正向反向无所谓 为什么要用拓扑排序 因为只有一个点所有到他的边都被走过,关于到它的期望值才算真正确定 */ #include<iostream> #include<cstring> #include<cstdio> #include<queue> #include<stack> using namespace std; int n,m,x,y,z,head[100010],tail,ru[100010],chu[100010]; bool flag[100010]; double ans[100010]; queue<int>qwq; struct in {int to,ne,co; }ter[200020]; inline void build(int f,int l,int c) {ter[++tail]=(in){l,head[f],c},head[f]=tail; } int main() {memset(head,-1,sizeof(head));scanf("%d%d",&n,&m);for(int i=1;i<=m;i++)scanf("%d%d%d",&x,&y,&z),build(y,x,z),ru[x]++,chu[x]++;//反向建图,因为从1跑不到的点肯定反向建图也跑不到1 for(int i=1;i<=n;i++)if(!ru[i])//如果原图该点,没有出边(终点) qwq.push(i);while(!qwq.empty()){int qaq=qwq.front();qwq.pop();//这里可以换成栈,跑的还更快,虽然我不知道为啥 for(int i=head[qaq];i>0;i=ter[i].ne){int t=ter[i].to;double gai=1.0/chu[t];ans[t]+=(ans[qaq]+ter[i].co)*gai;//求期望的必要步骤嘛qwq ru[t]--;if(!ru[t])qwq.push(t);} }for(int i=1;i<=n;i++)printf("%.2lf ",ans[i]);//printf("%.2lf",ans[1]); } /*关于这个反向拓扑排序可以的原因 因为每一个点都可以到达终点,所以无论正向反向,所有的从1到n的路径的期望值都不会变 所以正向反向无所谓 为什么要用拓扑排序 因为只有一个点所有到他的边都被走过,关于到它的期望值才算真正确定 */