背景
夜夜很贪玩。
描述
威尼斯是著名的水城。由n个岛和m座桥。岛从1到n编号。
夜夜是一名到威尼斯游玩的游客,她觉得每个岛都很有意思。因此她每次都会随机选择一个与当前岛相邻的岛去参观【同一座岛可以重复参观】。每座桥有一个权值At, 走过这座桥需要花费At个单位的时间, 桥可以双向通过。
夜夜初始在1号岛,她希望最终能到n号岛去。
那么夜夜到达n号岛的期望时间是多少呢?
答案保留一位小数。
格式
输入格式
第一行有两个整数n和m,表示岛屿个数与桥的个数。
之后m行,每行有三个整数u,v和At。其中1<=u,v<=n,表示有一座在岛u和岛v之间的桥,其权值为At。
输出格式
输出答案,答案四舍五入保留到一位小数。
限制
对于30%的数据
2<=n<=10
对于另外10%的数据
保证数据是一条链
对于另外10%的数据
保证数据是一个环,且1号岛与n号岛相连。
对于100%的数据
2<=n<=200
m<=n(n-1)/2
1<=At<=1000
数据保证每个岛和其余的都是联通的。且图中不存在重边。
每一个测试点时限1秒。
咱自己出的题。。结果自己的程序精度被卡了。。
这题是裸的高斯消元
根据期望的计算方法如下建立方程
for (int i=1;i<n;i++)
{
double siz=G[i].size();
mat[i][i]=-siz;
for (int j=0;j<G[i].size();j++)
mat[i][G[i][j]]=1.0;
for (int j=0;j<G[i].size();j++)
mat[i][n+1]+=(double)G1[i][j];
mat[i][n+1]/=siz;
}
mat[n][n]=1;
然后你就被卡精度了!!
分析问题所在的话是因为进行了/siz操作
那么怎么办呢?
把所有的方程*siz就可以了
for (int i=1;i<n;i++)
{
double siz=G[i].size();
mat[i][i]=-1;
for (int j=0;j<G[i].size();j++)
mat[i][G[i][j]]=1.0;
for (int j=0;j<G[i].size();j++)
mat[i][n+1]+=(double)G1[i][j];
}
mat[n][n]=1;
然后直接上高斯消元即可
最后要调整一下eps。。。嗯就是这样
#include<cstdio>
#include<vector>
#include<iostream>
using namespace std;
const int Maxn=2000;
double mat[Maxn][Maxn];
vector<int> G[Maxn];
vector<int> G1[2000];
int tot;
void gauss(){
int now=1;
for(int i=1;i<=tot;i++){
int j;
for(j=now;!mat[j][now]&&j<=tot;j++);
for(int k=1;k<=tot+1;k++)swap(mat[now][k],mat[j][k]);
for(int j=1;j<=tot;j++)
if(j!=now){
double t=mat[j][now]/mat[now][now];
for(int k=1;k<=tot+1;k++)
mat[j][k]-=t*mat[now][k];
}
now++;
}
for (int i=1;i<=tot;i++) mat[i][tot+1]/=(-mat[i][i]);
}
int n,m;
int main(){
//freopen("data.in","r",stdin);
//freopen("data.ans","w",stdout);
scanf("%d%d",&n,&m);
for (int i=1;i<=m;i++)
{
int x,y,t;
scanf("%d%d%d",&x,&y,&t);
G[x].push_back(y);
G[y].push_back(x);
G1[x].push_back(t);
G1[y].push_back(t);
}
tot=n;
for (int i=1;i<n;i++){
double siz=G[i].size();
mat[i][i]=-siz;
for (int j=0;j<G[i].size();j++){
// mat[i][G[i][j]]=1.0/siz;
mat[i][G[i][j]]=1.0;
//mat[i][G[i][j]]=1.0/(double)G[G[i][j]].size();
}
for (int j=0;j<G[i].size();j++)
{
mat[i][n+1]+=(double)G1[i][j];
//mat[i][G[i][j]]=1.0/(double)G[G[i][j]].size();
}
//mat[i][n+1]/=siz;
}
mat[n][n]=1;
/*for (int i=1;i<=n;i++){
for(int j=1;j<=n+1;j++)
cout<<mat[i][j]<<" ";
cout<<endl;
}*/
gauss();
// for (int i=1;i<=n;i++){
// printf("F[%d]=",i);
// cout<<mat[i][n+1]<<endl;
// }
double eps=0.000001;
printf("%.1f\n",mat[1][n+1]+eps);
return 0;
}