1. 程式人生 > >[BZOJ4061][Cerc2012]Farm and factory

[BZOJ4061][Cerc2012]Farm and factory

HA amp 改善 con pri times using 所在 LG

bzoj
鑒於是權限題,放一下題面。

Description

向Byteland的國王Bitolomew致敬!國王Bitolomew認為Byteland是一個獨一無二的國家。它太小了,它所有的市民(包括國外)都只在農場或工廠之一工作,其中農場和工廠是兩個不同的城市。因此每天早晨,每個城市的居民都在去這兩個城市的路上通行。Byteland的交通網絡包括一些連接兩個不同城市的無向的道路,道路不會連向國家之外的城市(但是隧道和橋可能會這樣)。兩個城市間可能存在多條無向的道路。保證農場和工廠與所有城市連通。幾個月前,為了改善交通狀況,國王Bitolomew出臺了過路費的政策,需要每個市民每次在通過相應道路時支付固定的費用Bitolomew希望這能引導市民重新考慮他們的上班路線,從而使得交通更加均勻暢通。國王的點子被他的諫者證明是不夠完美的。每個Byteland的市民現在都開始走起了最便宜的上班路線。國王Bitolomew完全沒想到會出現這種情況,然而過路費帶來的收入著實提高了國家財政的收入。事實上,國王現在的經濟狀況實在是太好了,所以他準備在一個新的首都建一個新的城堡。新的首都必須和一些其他的城市通過無向的道路相連,這樣才能從新首都到達每個城市。新建的道路可以設定非負的過路費(特別地,這裏的過路費可以不是整數)。國王Bitolomew真的很討厭車輛路過他的城堡所產生的噪聲。他希望通過合理設定新道路的過路費使得從任意除了新首都之外的城市v到農場或工廠都不會經過新首都(註意這裏v還包括農場和工廠)。另外,由於國王也要交過路費,所以他希望最小化從新首都到其他每個城市的平均過路費。請你幫助國王計算一下最小可能的平均值是多少吧。

Input

第一行一個正整數\(T\),表示有\(T\)組數據。
每組數據第一行兩個正整數\(n\)\(m\),表示Byteland有\(n\)個城市和\(m\)條道路,\(2\le n\le10^5,1\le m\le3\times10^5\)
接下來\(m\)行,每行三個整數表示城市\(u\)和城市\(v\)之間有一條過路費為\(c\)的道路,\(1\le u,v \le n,u\neq v, 0\le c\le 10^6\)。兩個城市間可能存在多條無向的道路。
農場所在的城市標號為\(1\),工廠所在的城市標號為\(2\)

Output

對於每組數據輸出一行,最小可能的從新首都到其他點所需過路費的平均值。

你的答案應該和標準答案誤差不超過\(10^{-8}\)

Sample Input

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

Sample Output

1.833333333333

sol

最小化平均過路費就是最小化總過路費。
我們設從\(1\)出發到每個點的最短路是\(f[i]\),從\(2\)出發到每個點的最短路是\(g[i]\),從新點出發到每個點的最短路是\(s[i]\)。新點到\(1,2\)號點的最短路是\(A,B\)
為了保證最短路不經過新點,就需要滿足:\(s_i+A\ge f_i,s_i+B\ge g_i\)
同時根據最短路的定義,有\(s_i+f_i\ge A,s_i+g_i\le B\)


我們要最小化\(\sum s_i\),所以\(s_i=\max(|A-f_i|,|B-g_i|)\)
發現是個切比雪夫距離的式子,所以直接排個序取中位數即可。

code

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
int gi(){
    int x=0,w=1;char ch=getchar();
    while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
    if (ch=='-') w=0,ch=getchar();
    while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
    return w?x:-x;
}
#define ll long long
#define pi pair<ll,int>
#define mk make_pair
const int N = 1e5+5;
const int M = 6e5+5;
int T,n,m,to[M],nxt[M],ww[M],head[N],cnt,vis[N];
ll f[N],g[N];
priority_queue<pi,vector<pi>,greater<pi> >Q;
void link(int u,int v,int w){
    to[++cnt]=v;nxt[cnt]=head[u];ww[cnt]=w;head[u]=cnt;
}
void Dijkstra(int s,ll *dis){
    memset(vis,0,sizeof(vis));
    dis[s]=0;Q.push(mk(0,s));
    while (!Q.empty()){
        int u=Q.top().second;Q.pop();
        if (vis[u]) continue;vis[u]=1;
        for (int e=head[u];e;e=nxt[e])
            if (dis[to[e]]>dis[u]+ww[e])
                dis[to[e]]=dis[u]+ww[e],Q.push(mk(dis[to[e]],to[e]));
    }
}
int main(){
    T=gi();while (T--){
        n=gi();m=gi();
        memset(head,0,sizeof(head));cnt=0;
        for (int i=1;i<=m;++i){
            int u=gi(),v=gi(),w=gi();
            link(u,v,w);link(v,u,w);
        }
        memset(f,63,sizeof(f));memset(g,63,sizeof(g));
        Dijkstra(1,f);Dijkstra(2,g);
        for (int i=1;i<=n;++i){
            ll x=f[i],y=g[i];
            f[i]=x+y,g[i]=x-y;
        }
        sort(f+1,f+n+1);sort(g+1,g+n+1);f[0]=g[0]=0;
        for (int i=1;i<=n;++i) f[i]+=f[i-1],g[i]+=g[i-1];
        if (n&1) printf("%.8lf\n",1.0*(f[n]-f[n/2]-f[n/2+1]+g[n]-g[n/2]-g[n/2+1])/(2.0*n));
        else printf("%.8lf\n",1.0*(f[n]-2*f[n/2]+g[n]-2*g[n/2])/(2.0*n));
    }
    return 0;
}

[BZOJ4061][Cerc2012]Farm and factory