码迷,mamicode.com
首页 > 其他好文 > 详细

BZOJ 3143: [Hnoi2013]游走( 高斯消元 )

时间:2015-12-03 22:49:40      阅读:195      评论:0      收藏:0      [点我收藏+]

标签:

技术分享

我一开始的想法是设f(x)表示点x到N路径的期望长度, 那么f(u) = (∑f(v)+w(u,v)) / degreeu, f(N)=0, 我们代入入消元应该可以得到f(1)关于各条边长的关系式f(1)=∑we..然后贪心, 按照他们的系数来给边权...但是不会实现..但是我感觉是可行的..PoPoQQQ题解:http://blog.csdn.net/PoPoQQQ/article/details/42234607

-----------------------------------------------------------------------

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
 
using namespace std;
 
typedef pair<int, int> pii;
typedef long double ld;
 
const int maxn = 509;
 
ld mat[maxn][maxn], p[1000000];
int deg[maxn], N, M;
pii Eg[1000000];
 
struct edge {
int to;
edge* next;
} E[maxn * maxn], *pt = E, *head[maxn];
 
void AddEdge(int u, int v) {
deg[pt->to = v]++; pt->next = head[u]; head[u] = pt++;
}
 
void Init() {
memset(deg, 0, sizeof deg);
scanf("%d%d", &N, &M); N--;
for(int i = 0; i < M; i++) {
int u, v;
scanf("%d%d", &u, &v);
Eg[i] = make_pair(--u, --v);
AddEdge(u, v);
AddEdge(v, u);
}
}
 
void Work() {
for(int i = 0; i < N; i++) {
int r = i;
for(int j = i; ++j < N; )
if(fabs(mat[j][i]) > fabs(mat[r][i])) r = j;
if(r != i) {
for(int j = 0; j <= N; j++)
swap(mat[r][j], mat[i][j]);
}
for(int j = i; ++j < N; ) {
ld t = mat[j][i] / mat[i][i];
for(int k = i; k <= N; k++)
mat[j][k] -= mat[i][k] * t;
}
}
for(int i = N; i--; ) {
for(int j = i; ++j < N; )
mat[i][N] -= mat[i][j] * mat[j][N];
mat[i][N] /= mat[i][i];
}
}
 
bool Cmp(const ld &i, const ld &j) {
return i > j;
}
 
int main() {
freopen("test.in", "r", stdin);
freopen("test.out", "w", stdout);
Init();
memset(mat, 0, sizeof mat);
mat[0][N]--;
for(int i = 0; i < N; i++) {
for(edge* e = head[i]; e; e = e->next)
if(e->to != N) mat[i][e->to] += ld(1) / deg[e->to];
mat[i][i]--;
}
Work();
memset(p, 0, sizeof p);
for(int i = 0; i < M; i++) {
pii &t = Eg[i];
p[i] = mat[t.first][N] / deg[t.first] + mat[t.second][N] / deg[t.second];
}
sort(p, p + M, Cmp);
ld ans = 0;
for(int i = 0; i < M; i++)
ans += p[i] * (i + 1);
printf("%.3lf\n", (double) ans);
return 0;
}

----------------------------------------------------------------------- 

 

3143: [Hnoi2013]游走

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 1526  Solved: 660
[Submit][Status][Discuss]

Description

一个无向连通图,顶点从1编号到N,边从1编号到M。 
小Z在该图上进行随机游走,初始时小Z在1号顶点,每一步小Z以相等的概率随机选 择当前顶点的某条边,沿着这条边走到下一个顶点,获得等于这条边的编号的分数。当小Z 到达N号顶点时游走结束,总分为所有获得的分数之和。 
现在,请你对这M条边进行编号,使得小Z获得的总分的期望值最小。

Input

第一行是正整数N和M,分别表示该图的顶点数 和边数,接下来M行每行是整数u,v(1≤u,v≤N),表示顶点u与顶点v之间存在一条边。 输入保证30%的数据满足N≤10,100%的数据满足2≤N≤500且是一个无向简单连通图。

Output

仅包含一个实数,表示最小的期望值,保留3位小数。

Sample Input

3 3
2 3
1 2
1 3

Sample Output

3.333

HINT

(1,2)编号为1,边(1,3)编号2,边(2,3)编号为3

Source

 

BZOJ 3143: [Hnoi2013]游走( 高斯消元 )

标签:

原文地址:http://www.cnblogs.com/JSZX11556/p/5017611.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!