BZOJ 3143: [Hnoi2013]游走( 高斯消元 )
我一开始的想法是设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 MBSubmit: 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
2 3
1 2
1 3
Sample Output
3.333
HINT
边(1,2)编号为1,边(1,3)编号2,边(2,3)编号为3。
Source