题目描述
一个无向连通图,顶点从1编号到N,边从1编号到M。 小Z在该图上进行随机游走,初始时小Z在1号顶点,每一步小Z以相等的概率随机选 择当前顶点的某条边,沿着这条边走到下一个顶点,获得等于这条边的编号的分数。当小Z 到达N号顶点时游走结束,总分为所有获得的分数之和。 现在,请你对这M条边进行编号,使得小Z获得的总分的期望值最小。
输入输出格式
输入格式:
第一行是正整数N和M,分别表示该图的顶点数 和边数,接下来M行每行是整数u,v(1<=u,v<=N),表示顶点u与顶点v之间存在一条边。 输入保证30%的数据满足N<=10,100%的数据满足2<=N<=500且是一个无向简单连通图。
输出格式:
仅包含一个实数,表示最小的期望值,保留3位小数。
输入输出样例
说明
边(1,2)编号为1,边(1,3)编号2,边(2,3)编号为3。
#include<iostream> #include<cstdio> #include<cmath> #include<cstring> #include<algorithm> using namespace std; const int N=505; const int M=2e5+5; const double eps=1e-8; inline int read() { char c=getchar();int num=0; for(;!isdigit(c);c=getchar()); for(;isdigit(c);c=getchar()) num=num*10+c-'0'; return num; } int cmp(double a,double b) { if(fabs(a-b)<=eps) return 0; if(fabs(a)-fabs(b)>eps) return 1; return -1; } int n,m; double mat[N][N]; //Gauss Matrix int deg[N]; double p[N]; struct Edge { int u,v; double p; bool operator <(const Edge &a) const { // return cmp(this->p,a.p)==-1; return p<a.p; } }edge[M]; void Gauss() { for(int i=1,p;i<=n;++i) { p=i; for(int j=i+1;j<=n;++j) { if(cmp(mat[p][i],mat[j][i])==-1) p=j; } if(p!=i) { for(int j=i;j<=n+1;++j) { swap(mat[p][j],mat[i][j]); } } for(int j=i+1;j<=n;++j) { double ratio=mat[j][i]/mat[i][i]; for(int k=i;k<=n+1;++k) { mat[j][k]-=mat[i][k]*ratio; } } } for(int i=n;i;--i) { for(int j=i+1;j<=n;++j) { mat[i][n+1]-=mat[i][j]*mat[j][n+1]; } mat[i][n+1]/=mat[i][i]; } } double ans; int main() { n=read(),m=read(); for(int i=1,u,v;i<=m;++i) { u=read(),v=read(); edge[i].u=u,edge[i].v=v; ++deg[u],++deg[v]; } for(int i=1;i<=n;++i) mat[i][i]=-1; for(int i=1;i<=m;++i) { mat[edge[i].u][edge[i].v]+=1.0/deg[edge[i].v]; mat[edge[i].v][edge[i].u]+=1.0/deg[edge[i].u]; } for(int i=1;i<n;++i) mat[n][i]=0; mat[n][n]=1; mat[1][n+1]=-1; // for(int i=1;i<=n;++i) // { // for(int j=1;j<=n+1;++j) // { // printf("%.3lf ",mat[i][j]); // } // puts(""); // } Gauss(); for(int i=1;i<=m;++i) { edge[i].p=mat[edge[i].u][n+1]/(double)deg[edge[i].u]+mat[edge[i].v][n+1]/(double)deg[edge[i].v]; } sort(edge+1,edge+m+1); for(int i=1;i<=m;++i) { ans+=edge[i].p*(m-i+1); } printf("%.3lf",ans); return 0; }