zoukankan      html  css  js  c++  java
  • bzoj3143 [HNOI2013]游走

    题目链接

    solution

    如果可以统计出每条边期望走多少次,那么只要按照经过的次数从小到大降序编号就能保证最终得分最小了。

    统计每条边走的次数不好统计,但是统计点的经过次数似乎不难。那么边的经过次数就是他所连接的两点经过次数分别除以这两个点的度数之和。

    然后考虑如何统计每个点的经过次数。

    (f[i])表示(i)这个点被经过的次数。那么就有(f[u]=sumlimits_{w(u,v)}^n frac{f[v]}{du[v]})

    对于第一个点一开始就被经过了一次,所以有(f[1]=sumlimits_{w(1,v)}frac{f[v]}{du[v]}+1)。因为最后一个点只会被经过一次而且与最后一个点向连的边,最后一个点无法对其产生贡献,所以最后一个点不要考虑。

    列方程高斯消元解出来就行了。

    code

    /*
    * @Author: wxyww
    * @Date:   2020-04-27 20:14:39
    * @Last Modified time: 2020-04-27 20:25:22
    */
    #include<cstdio>
    #include<cmath>
    #include<iostream>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #include<vector>
    #include<ctime>
    using namespace std;
    typedef long long ll;
    const int N = 510;
    ll read() {
    	ll x = 0,f = 1;char c = getchar();
    	while(c < '0' || c > '9') {
    		if(c == '-') f = -1; c = getchar();
    	}
    	while(c >= '0' && c <= '9') {
    		x = x * 10 + c - '0'; c = getchar();
    	}
    	return x * f;
    }
    struct node {
    	int v,nxt;
    }e[N * N];
    int head[N],ejs = 1;
    void add(int u,int v) {
    	e[++ejs].v = v;e[ejs].nxt = head[u];head[u] = ejs;
    }
    double a[N][N];
    int du[N];
    void Guass(int n) {
    	for(int i = 1;i <= n;++i) {
    		int t = i;
    		for(int j = i + 1;j <= n;++j)
    			if(a[j][i] > a[t][i]) t = j;
    
    		if(fabs(a[t][i]) < 1e-8) continue;
    		swap(a[t],a[i]);
    
    		double div = a[i][i];
    		for(int j = i;j <= n + 1;++j) a[i][j] /= div;
    
    		for(int j = 1;j <= n;++j) {
    			if(j == i) continue;
    			div = a[j][i];
    			for(int k = i;k <= n + 1;++k)
    				a[j][k] -= div * a[i][k]; 
    		}
    	}
    }
    
    double ans[N * N];
    int tot;
    int main() {
    	int n = read(),m = read();
    	for(int i = 1;i <= m;++i) {
    		int u = read(),v = read();
    		add(u,v);add(v,u);
    		du[u]++;du[v]++;
    	}
    
    	a[1][n] = 1;
    
    	for(int u = 1;u < n;++u) {
    		a[u][u] = 1;
    		for(int i = head[u];i;i = e[i].nxt ) {
    			int v = e[i].v;
    			if(v == n) continue;
    			a[u][v] -= 1.0 / du[v];
    		}
    	}
    
    	Guass(n - 1);
    
    	for(int i = 2;i <= ejs;i += 2)
    		ans[++tot] = a[e[i].v][n] / du[e[i].v] + a[e[i ^ 1].v][n] / du[e[i ^1].v];
    
    	sort(ans + 1,ans + tot + 1);
    	double anss = 0;
    	for(int i = 1;i <= tot;++i)
    		anss += ans[i] * (tot - i + 1);
    
    	printf("%.3lf
    ",anss);
    	return 0;
    }
    
  • 相关阅读:
    HDU Problem 1811 Rank of Tetris【拓扑排序+并查集】
    POJ Problem 2367 Genealogical tree【拓扑排序】
    HDU Problem 2647 Reward【拓扑排序】
    HDU Problem 1285 确定比赛名次【拓扑排序】
    HDU Problem HDU Today 【最短路】
    HDU Problem 3665 Seaside【最短路】
    HDU Problem 一个人的旅行 【最短路dijkstra】
    HDU Problem 1596 find the safest road【最短路dijkstra】
    Beyond Compare文本合并进行内容替换要注意什么
    用这些工具都可以比较代码的差异
  • 原文地址:https://www.cnblogs.com/wxyww/p/bzoj3143.html
Copyright © 2011-2022 走看看