BZOJ 3143 HNOI2013 游走 高斯消元 期望

這道題是我第一次使用高斯消元解決期望類的問題,首發A了,感覺爽爽的....

不過筆者在做完后發現了一些問題,在原文的后面進行了說明。

?

中文題目,就不翻大意了,直接給原題:

  一個無向連通圖,頂點從1編號到N,邊從1編號到M。?

  小Z在該圖上進行隨機游走,初始時小Z在1號頂點,每一步小Z以相等的概率隨機選 擇當前頂點的某條邊,沿著這條邊走到下一個頂點,獲得等于這條邊的編號的分數。當小Z 到達N號頂點時游走結束,總分為所有獲得的分數之和。?

  現在,請你對這M條邊進行編號,使得小Z獲得的總分的期望值最小。

  輸出最小的總分期望值。

?

Solution:

  這題貪心很明顯,哪條邊走過次數的期望最大,它就應該獲得最小的編號。

  所以假設我們已經求出了每條邊走過的期望,我們就可以給它們并編上號了。

  怎么算出每條邊走過的期望呢?

  每條邊連接著兩個點u,v,很明顯的,當我們經過這條邊,一定是從兩個點中的某一個進入。

  所以走過邊l的期望=走過u點的期望次數*從u點走到l上的概率+走過v點的期望次數*從v點走到l上的概率 (其中從i點走到它連接邊的概率為1/d[i],d[i]為i的度數)

  即:E[l]=e[u]/d[u]+e[v]/d[v]

  可是我們只知道e[n]=0。但我們還知道這些點之間哪些是連通的,從而可以得出它們之間的關系:

  

  我們就可以利用這些點之間的關系建立起方程組,從而使用高斯消元求解。

  別忘了,點求解完還要帶回到每條邊上去哦....

  

  附Bzoj上的AC代碼(codevs上過不了...我也不知道為什么...)

  

  1 /*
  2   Problem : Bzoj 3143 概率 & 高斯消元 
  3   Author : Robert Yuan
  4   Memory : 15604 kb
  5   Time : 628 MS    
  6   Result : Accept
  7 */
  8 #include <cmath> 
  9 #include <cstdio>
 10 #include <cstring>
 11 #include <cstdlib>
 12 #include <algorithm>
 13 
 14 using namespace std;
 15 
 16 #define maxn 520
 17 
 18 struct Node{
 19     int data,next;
 20 }node[maxn*maxn<<1];
 21 
 22 struct Edge{
 23     int u,v;
 24     double w;
 25 }edge[maxn*maxn<<1];
 26 
 27 #define now node[point].data
 28 #define then node[point].next
 29 
 30 int n,m,cnt;
 31 int head[maxn],deg[maxn];
 32 const double eps=1e-6;
 33 double w[maxn][maxn],rec_x[maxn],ans;
 34 
 35 bool cmp(const Edge A,const Edge B){
 36     return A.w>B.w;
 37 }
 38 
 39 inline int in(){
 40     int x=0;char ch=getchar();
 41     while(ch>'9' || ch<'0') ch=getchar();
 42     while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
 43     return x;
 44 }
 45 
 46 void add(int u,int v){
 47     node[++cnt].data=v;node[cnt].next=head[u];deg[u]++;head[u]=cnt;
 48     node[++cnt].data=u;node[cnt].next=head[v];deg[v]++;head[v]=cnt;
 49 }
 50 
 51 void prework(){
 52     n=in();m=in();
 53     int u,v;
 54     for(int i=1;i<=n;i++) head[i]=-1;
 55     for(int i=1;i<=m;i++)
 56         u=in(),v=in(),edge[i].u=u,edge[i].v=v,add(u,v); 
 57     int point;
 58     for(int i=1;i<=n;i++){
 59         w[i][i]=1;
 60         point=head[i];
 61         while(point!=-1){
 62             w[i][now]=-(double)1/deg[now];
 63             point=then;
 64         }
 65     }
 66     w[1][n+1]=1;
 67 }
 68 
 69 void Swap(int i,int j,int x){
 70     double t;
 71     for(int k=x+1;k<=n+1;k++)
 72         t=w[i][k],w[i][k]=w[j][k],w[j][k]=t;
 73 }
 74 
 75 void gauss(){
 76     int i,j;
 77     for(i=1,j=1;i<=n && j<=n;i++,j++){
 78         int max_r=i;
 79         for(int k=i+1;k<=n;k++)
 80             if(fabs(w[max_r][j])+eps<fabs(w[k][j]))
 81                 max_r=k;
 82         if(fabs(w[max_r][j])<eps){i--;continue;}
 83         if(max_r!=i) Swap(i,max_r,j);
 84         for(int k=i+1;k<=n;k++){
 85             double rate=w[k][j]/w[i][j];
 86             w[k][j]=0;
 87             for(int l=j+1;l<=n+1;l++)
 88                 w[k][l]-=w[i][l]*rate;
 89         }
 90     }
 91     
 92     for(int i=n;i>=1;i--)
 93         if(fabs(w[i][i])>eps){
 94             double ans_c=w[i][n+1];
 95             for(int k=i+1;k<=n;k++)
 96                 ans_c-=w[i][k]*rec_x[k];
 97             rec_x[i]=ans_c/w[i][i];
 98         }
 99 }
100 
101 void mainwork(){
102     gauss();
103     for(int i=1;i<=m;i++){
104         edge[i].w=rec_x[edge[i].u]/deg[edge[i].u]+rec_x[edge[i].v]/deg[edge[i].v];
105     }    
106     sort(edge+1,edge+m+1,cmp);
107     for(int i=1;i<=m;i++)
108         ans+=edge[i].w*i;
109     printf("%.3lf",ans);
110 }
111 
112 int main(){
113 #ifndef ONLINE_JUDGE
114     freopen("x.in","r",stdin);
115 #endif
116     prework();
117     mainwork();
118     return 0;
119 }
View Code

?

?

[以下是筆者后來發現的問題]

  首先感謝某位不愿意透露姓名的人堆同學復制了我的代碼,然后代入了樣例,結果:

  

  然后第三行是無解?可是答案卻能跑出來...于是我傻了...開始胡亂吹逼[畢竟這么久沒打了...]

  

  好吧,然后各種逼都被打敗了...(●—●)

  只能認真看看到底出了什么問題,于是發現這個式子有奧妙:

  

  左邊的e[i]表示走到i點的期望,右邊的e[j]表示走出j點的期望。

  “走到”和“走出”卻并不是一樣的!

  我們設e[i]表示走到i點的概率,e'[i]表示走出i點的概率。

  如果說i!=n那么走到就能走出,e[i]=e'[i];

  如果i==n那么就有e'[n]=0,e[n]=1他們倆不同...盡管都已知,而我們列式子的時候,將e'[n]作為未知數帶進別的點的式子里,但在n自己的式子中卻用的是e[n],導致兩個變量混淆。

  所以鑒于e'[n]=0,就將建立方程部分修改了一下:

  

  于是現在的式子就發生了變化,最后化出來的矩陣也變成了正常的樣子:

  

  這樣解出來的就是e[n]是到達n點的期望=1,當然在給邊設定權值的時候,我們用的都是e'[i],所以我們手動修改一下e'[n]=0就好了...

  下面是修改過后的代碼:

#include <cmath> 
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>using namespace std;#define maxn 520struct Node{int data,next;
}node[maxn*maxn<<1];struct Edge{int u,v;double w;
}edge[maxn*maxn<<1];#define now node[point].data
#define then node[point].nextint n,m,cnt;
int head[maxn],deg[maxn];
const double eps=1e-6;
double w[maxn][maxn],rec_x[maxn],ans;bool cmp(const Edge A,const Edge B){return A.w>B.w;
}inline int in(){int x=0;char ch=getchar();while(ch>'9' || ch<'0') ch=getchar();while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();return x;
}void add(int u,int v){node[++cnt].data=v;node[cnt].next=head[u];deg[u]++;head[u]=cnt;node[++cnt].data=u;node[cnt].next=head[v];deg[v]++;head[v]=cnt;
}void prework(){n=in();m=in();int u,v;for(int i=1;i<=n;i++) head[i]=-1;for(int i=1;i<=m;i++)u=in(),v=in(),edge[i].u=u,edge[i].v=v,add(u,v); int point;for(int i=1;i<=n;i++){w[i][i]=1;point=head[i];while(point!=-1){if(now!=n) w[i][now]=-(double)1/deg[now];else w[i][now]=0;point=then;}}w[1][n+1]=1;
}void Swap(int i,int j,int x){double t;for(int k=x+1;k<=n+1;k++)t=w[i][k],w[i][k]=w[j][k],w[j][k]=t;
}void gauss(){int i,j;for(i=1,j=1;i<=n && j<=n;i++,j++){int max_r=i;for(int k=i+1;k<=n;k++)if(fabs(w[max_r][j])+eps<fabs(w[k][j]))max_r=k;if(fabs(w[max_r][j])<eps){i--;continue;}if(max_r!=i) Swap(i,max_r,j);for(int k=i+1;k<=n;k++){double rate=w[k][j]/w[i][j];w[k][j]=0;for(int l=j+1;l<=n+1;l++)w[k][l]-=w[i][l]*rate;}}for(int i=n;i>=1;i--)if(fabs(w[i][i])>eps){double ans_c=w[i][n+1];for(int k=i+1;k<=n;k++)ans_c-=w[i][k]*rec_x[k];rec_x[i]=ans_c/w[i][i];}rec_x[n]=0;
}void mainwork(){gauss();for(int i=1;i<=m;i++){edge[i].w=rec_x[edge[i].u]/deg[edge[i].u]+rec_x[edge[i].v]/deg[edge[i].v];}    sort(edge+1,edge+m+1,cmp);for(int i=1;i<=m;i++)ans+=edge[i].w*i;printf("%.3lf",ans);
}int main(){
#ifndef ONLINE_JUDGEfreopen("x.in","r",stdin);
#endifprework();mainwork();return 0;
}
View Code

?

最后再次鳴謝人堆同學提出的問題,有問題才有進步嘛,歡迎大家提問哦...

轉載于:https://www.cnblogs.com/Robert-Yuan/p/4636355.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/374812.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/374812.shtml
英文地址,請注明出處:http://en.pswp.cn/news/374812.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

VS2019安全函數scanf_s問題

VS2017、VS2019等安全函數scanf_s問題&#xff1a; scanf()、gets()、fgets()、strcpy()、strcat() 等都是C語言自帶的函數&#xff0c;它們都是標準函數&#xff0c;但是它們都有一個缺陷&#xff0c;就是不安全&#xff0c;可能會導致數組溢出或者緩沖區溢出&#xff0c;讓黑…

eclipse啟動tomcat, http://localhost:8080無法訪問的解決方案

問題:&#xff1a; tomcat在eclipse里面能正常啟動&#xff0c;但在瀏覽器中訪問http://localhost:8080/不能訪問tomcat管理頁面&#xff0c;且報404錯誤。同時其他項目頁面也不能訪問。訪問的時候出現下列頁面: 現在關閉eclipse里面的tomcat&#xff0c;在tomcat安裝目錄下雙擊…

GWT EJB3 Maven JBoss 5.1集成教程

大家好&#xff0c; 在本文中&#xff0c;我們將演示如何正確集成GWT和EJB3 &#xff0c;以實現示例項目&#xff0c;使用maven進行構建并將其部署在JBoss 5.1應用服務器上。 實際上&#xff0c;您可以輕松地更改maven構建文件中的依賴關系&#xff0c;并將項目部署到您喜歡的…

VS2019注釋整段代碼

VS2019注釋整段代碼 1.注釋 先CTRLK&#xff0c;然后CTRLC 2.取消注釋&#xff1a; 先CTRLK&#xff0c;然后CTRLU 順便寫一下&#xff1a; VS code注釋整段代碼 Alt Shift A 注釋 CodeBlocks&#xff1a; CtrlShiftC注釋掉當前行或選中部分&#xff0c; CtrlShiftX解除注釋…

linux中的開機和關機命令

與關機、重新啟動相關的命令 * 將數據同步寫入硬盤中的命令 sync * 慣用的關機命令 shutdown * 重新啟動、關機 reboot halt poweroff sync 強制將內存中的數據寫入到硬盤當中。因為linux系統中&#xff0c;數據會緩存在內存當中&#xff0c;所以為了保證數據完整保存在硬盤…

如何在不到1ms的延遲內完成100K TPS

馬丁湯普森&#xff08;Martin Thompson&#xff09;和邁克爾巴克&#xff08;Michael Barker&#xff09;討論了通過采用一種新的基礎架構和軟件方法來構建HPC金融系統&#xff0c;以不到1ms的延遲處理超過100K TPS的問題。 一些技巧包括&#xff1a; 了解平臺 建模領域 明…

獲取時間C語言-按秒數

兩部分&#xff1a; 1.獲取秒數 2.獲取“年-月-日-時-分-秒” 1.獲取秒數 #include<time.h>//包含的頭文件int GetTime() {time_t t;t time(NULL);//另一種寫法是//time(t);//當time&#xff08;&#xff09;內參數為空時結果直接輸出&#xff0c;否則就會存儲在參數…

Spring的69個知識點

目錄 Spring 概述依賴注入Spring beansSpring注解Spring數據訪問Spring面向切面編程&#xff08;AOP&#xff09;Spring MVCSpring 概述 1. 什么是spring? Spring 是個java企業級應用的開源開發框架。Spring主要用來開發Java應用&#xff0c;但是有些擴展是針對構建J2EE平臺的…

python 編碼問題之終極解決

結合之前遇到的坑以及下面貼的這篇文章&#xff0c; 總結幾種python亂碼解決方案&#xff0c;如果遇到亂碼&#xff0c;不妨嘗試一下&#xff1f; 1&#xff0c;必備 #encodingutf-8 2, python編程環境編碼 import sys reload(sys) sys.setdefaultencoding(utf8) 3,不知道神馬…

GWT 2 Spring 3 JPA 2 Hibernate 3.5教程

本分步指南將介紹如何使用開發一個簡單的Web應用程序 Google的網絡工具包 &#xff08;GWT&#xff09;用于富客戶端&#xff0c;而Spring作為后端服務器端框架。 該示例Web應用程序將提供對數據庫執行CRUD&#xff08;創建檢索更新刪除&#xff09;操作的功能。 對于數據訪問層…

洛谷P1014 [NOIP1999 普及組] Cantor 表

現代數學的著名證明之一是 Georg Cantor 證明了有理數是可枚舉的。他是用下面這一張表來證明這一命題的&#xff1a; 代碼 import java.util.*; public class Main{public static void main(String[] args){//int x1 0;int i 0;Scanner sc new Scanner(System.in);int n s…

3522: [Poi2014]Hotel( 樹形dp )

枚舉中點x( 即選出的三個點 a , b , c 滿足 dist( x , a ) dist( x , b ) dist( x , c ) ) , 然后以 x 為 root 做 dfs , 顯然兩個位于 x 的同一顆子樹內的點是不可能被同時選到的 . 我們對 x 的每一顆子樹進行 dfs , 記錄下當前子樹中的點到 x 距離為 d ( 1 < d < n )…

第一沖刺階段工作總結02

1.昨天&#xff1a; 實驗簡單的安卓程序&#xff0c;開始具體的設計軟件界面。 2.今天&#xff1a; 繼續設計軟件頁面&#xff0c;由于安卓虛擬機過于遲緩&#xff0c;配置真機&#xff0c;學習如何在真機上運行程序。 3.遇到的困難&#xff1a; 真機配置不知道怎樣配置&#x…

JBoss 4.2.x Spring 3 JPA Hibernate教程第2部分

我們將繼續有關Spring 3 &#xff0c; Hibernate &#xff0c; JPA和JBoss 4.2.x – 4.3集成的教程 。 最后一步是創建一個Spring服務&#xff0c;以向最終用戶公開功能。 我們必須創建一個接口類和相關的實現類。 首先是接口類&#xff1a; package com.mycomp.myproject.se…

洛谷P1035 [NOIP2002 普及組] 級數求和

代碼 import java.util.Scanner;public class Main {public static void main(String args[]){Scanner sc new Scanner(System.in);int k sc.nextInt();int n 0;double Sn 0;while(Sn<k){n;Sn Sn 1.0/n;}System.out.println(n);} }這樣寫while循環體這需要每次加上1/…

『Luogu OJ』『C++』Level 1-1

關卡1-1&#xff0c;3道題 洛谷的第一個任務 任務說明&#xff1a;勇敢的邁出第一步&#xff0c;了解下語言和洛谷。跟著書本和老師走&#xff0c;不會難的。 要完成這個任務&#xff0c;請將以下的題目都AC掉&#xff08;即通過這道題目&#xff09;&#xff1a; 1.AB Problem…

Java中的Google ClientLogin實用程序

Google API的身份驗證和授權是當今需要與Google服務集成和信息交換的應用程序中的常見功能。 盡管大多數Google身份驗證過程是針對Web應用程序量身定制的&#xff0c;但它也可用于桌面和已安裝的應用程序。 對于桌面應用程序&#xff0c;Google建議使用稱為ClientLogin的身份驗…

九度OJ1486 /POJ 1029/2012北京大學研究生復試上機

wa到死&#xff01;wa到死&#xff01;這是一個看著簡單&#xff0c;坑及其多的題&#xff01; 坑一&#xff1a;POJ上是單組輸入&#xff0c;九度上是多組輸入&#xff0c;媽蛋要是研究生復試遇到這種大坑肯定死掉啊&#xff01;而且對于codeforces比較習慣的 同學肯定會覺得巨…

P1046 [NOIP2005 普及組] 陶陶摘蘋果

題目描述 陶陶家的院子里有一棵蘋果樹&#xff0c;每到秋天樹上就會結出 1010 個蘋果。蘋果成熟的時候&#xff0c;陶陶就會跑去摘蘋果。陶陶有個 3030 厘米高的板凳&#xff0c;當她不能直接用手摘到蘋果的時候&#xff0c;就會踩到板凳上再試試。 現在已知 1010 個蘋果到地面…

新手不了解Xcode和mac系統可能犯得錯誤和我的建議

我是學iOS剛入門的新手&#xff0c;本人裝的時黑蘋果&#xff0c;我是喜歡完美的人&#xff0c;但黑蘋果又是不完美的系統&#xff0c;比如關不了機啊&#xff0c;和顯卡驅動不了啊&#xff0c;當自己的電腦出現白屏和卡頓的時候氣的沒脾氣。我是一個新手。開始學的時java但我喜…