1. 程式人生 > >[HNOI2013]遊走

[HNOI2013]遊走

dcm -- style 一行 pre n-1 noi cstring 表示

題目描述

一個無向連通圖,頂點從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: 復制
3 3
2 3
1 2
1 3
輸出樣例#1: 復制
3.333

說明

邊(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 }

[HNOI2013]遊走