您的位置:首页 > 其它

vijos P1966 夜夜的旅游计划

2015-10-03 23:56 441 查看


背景

夜夜很贪玩。


描述

威尼斯是著名的水城。由n个岛和m座桥。岛从1到n编号。

夜夜是一名到威尼斯游玩的游客,她觉得每个岛都很有意思。因此她每次都会随机选择一个与当前岛相邻的岛去参观【同一座岛可以重复参观】。每座桥有一个权值At, 走过这座桥需要花费At个单位的时间, 桥可以双向通过。

夜夜初始在1号岛,她希望最终能到n号岛去。

那么夜夜到达n号岛的期望时间是多少呢?

答案保留一位小数。


格式

输入格式

第一行有两个整数n和m,表示岛屿个数与桥的个数。

之后m行,每行有三个整数u,v和At。其中1<=u,v<=n,表示有一座在岛u和岛v之间的桥,其权值为At。

输出格式

输出答案,答案四舍五入保留到一位小数。


样例1

样例输入1[复制]

3 3
1 2 1
2 3 1
3 1 1


样例输出1[复制]

2.0



样例2

样例输入2[复制]

5 4
1 2 1
2 3 1
3 4 1
4 5 1


样例输出2[复制]

16.0



限制

对于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

=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

=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

=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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: