[HNOI2013]游走
题目描述
一个无向连通图,顶点从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。
算出每条边的期望走过次数
贪心,期望大的给小编号,答案最小
每条边的期望走过次数可以由两个端点的期望次数算出来
E[i]=e[u]/d[u]+e[v]/d[v]
那么问题就转为求点期望走过次数
对于每一个点u
我们有e[u]=∑(e[v]/d[v])
特例:
1是起点,期望步数+1
n是终点,期望为0
于是列出n-1个方程,高斯消元
此代码在洛谷玄学WA,但BZOJ能AC
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 using namespace std; 7 struct link 8 { 9 int u,v; 10 }Link[500101]; 11 struct Node 12 { 13 int next,to; 14 }edge[500101]; 15 int head[601],num,n,m; 16 double a[601][601],ans[601],d[601],E[500101],anss; 17 void add(int u,int v) 18 { 19 num++; 20 edge[num].next=head[u]; 21 head[u]=num; 22 edge[num].to=v; 23 } 24 const double eps=1e-12; 25 int dcmp(double x) 26 { 27 if (x<=eps&&x>=-eps) return 0; 28 return (x>0)?1:-1; 29 } 30 void gauss() 31 {int i,now,j,k; 32 for (i=1;i<=n;i++) 33 { 34 now=i; 35 for (j=i+1;j<=n;j++) 36 if (dcmp(a[now][i]-a[j][i])<0) 37 now=j; 38 if (now!=i) 39 for (j=i;j<=n+1;j++) 40 swap(a[now][j],a[i][j]); 41 for (j=i+1;j<=n;j++) 42 if (dcmp(a[j][i])) 43 { 44 double t=a[j][i]/a[i][i]; 45 for (k=i+1;k<=n+1;k++) 46 a[j][k]-=a[i][k]*t; 47 } 48 } 49 for (i=n;i>=1;i--) 50 { 51 for (j=i+1;j<=n;j++) 52 { 53 a[i][n+1]-=a[i][j]*ans[j]; 54 } 55 ans[i]=a[i][n+1]/a[i][i]; 56 } 57 } 58 int main() 59 {int i,u,v,j; 60 cin>>n>>m; 61 for (i=1;i<=m;i++) 62 { 63 scanf("%d%d",&u,&v); 64 add(u,v);add(v,u); 65 Link[i].u=u;Link[i].v=v; 66 d[u]+=1.0;d[v]+=1.0; 67 } 68 a[1][n]=-1.0; 69 for (i=1;i<n;i++) 70 a[i][i]=-1.0; 71 for (i=1;i<n;i++) 72 { 73 for (j=head[i];j;j=edge[j].next) 74 { 75 int v=edge[j].to; 76 if (v!=n) 77 { 78 a[i][v]=1.0/d[v]; 79 } 80 } 81 } 82 n--; 83 gauss(); 84 for (i=1;i<=m;i++) 85 E[i]=ans[Link[i].u]/d[Link[i].u]+ans[Link[i].v]/d[Link[i].v]; 86 sort(E+1,E+m+1); 87 for (i=1;i<=m;i++) 88 anss+=E[i]*(m-i+1.0); 89 printf("%.3lf\n",anss); 90 }