P3199 [HNOI2009]最小圈 01分數規劃
阿新 • • 發佈:2019-02-24
n) noi2009 以及 平均值 有向圖 pan 數據 pac sca
裸題,第二個權值是自己點的個數。二分之後用spfa判負環就行了。
題目描述 考慮帶權的有向圖G=(V,E)G=(V,E)G=(V,E)以及w:E→Rw:E\rightarrow Rw:E→R,每條邊e=(i,j)(i≠j,i∈V,j∈V)e=(i,j)(i\neq j,i\in V,j\in V)e=(i,j)(i≠j,i∈V,j∈V)的權值定義為wi,jw_{i,j}wi,j?,令n=∣V∣n=|V|n=∣V∣。c=(c1,c2,?,ck)(ci∈V)c=(c_1,c_2,\cdots,c_k)(c_i\inV)c=(c1?,c2?,?,ck?)(ci?∈V)是GGG中的一個圈當且僅當(ci,ci+1)(1≤i<k)(c_i,c_{i+1})(1\le i<k)(ci?,ci+1?)(1≤i<k)和(ck,c1)(c_k,c_1)(ck?,c1?)都在EEE中,這時稱kkk為圈ccc的長度同時令ck+1=c1c_{k+1}=c_1ck+1?=c1?,並定義圈c=(c1,c2,?,ck)c=(c_1,c_2,\cdots,c_k)c=(c1?,c2?,?,ck?)的平均值為μ(c)=∑i=1kwci,ci+1/k\mu(c)=\sum\limits_{i=1}^{k} w_{c_i,c_{i+1}}/kμ(c)=i=1∑k?wci?,ci+1??/k,即ccc上所有邊的權值的平均值。令μ′(c)=Min(μ(c))\mu‘(c)=Min(\mu(c))μ′(c)=Min(μ(c))為GGG中所有圈ccc的平均值的最小值。現在的目標是:在給定了一個圖G=(V,E)G=(V,E)G=(V,E)以及w:E→Rw:E\rightarrow Rw:E→R之後,請求出GGG中所有圈ccc的平均值的最小值μ′(c)=Min(μ(c))\mu‘(c)=Min(\mu(c))μ′(c)=Min(μ(c)) 輸入輸出格式 輸入格式: 第一行2個正整數,分別為nnn和mmm,並用一個空格隔開,只用n=∣V∣,m=∣E∣n=|V|,m=|E|n=∣V∣,m=∣E∣分別表示圖中有nnn個點mmm條邊。 接下來m行,每行3個數i,j,wi,ji,j,w_{i,j}i,j,wi,j?,表示有一條邊(i,j)(i,j)(i,j)且該邊的權值為wi,jw_{i,j}wi,j?。輸入數據保證圖G=(V,E)G=(V,E)G=(V,E)連通,存在圈且有一個點能到達其他所有點。 輸出格式: 請輸出一個實數μ′(c)=Min(μ(c))\mu‘(c)=Min(\mu(c))μ′(c)=Min(μ(c)),要求輸出到小數點後8位。
題幹:
#include<iostream> #include<cstdio> #include<cmath> #include<ctime> #include<queue> #include<algorithm> #include<cstring> using namespace std; #define duke(i,a,n) for(register int i = a;i <= n;++i) #define lv(i,a,n) for(register int i = a;i >= n;--i) #define clean(a) memset(a,0,sizeof(a)) const int INF = 1 << 30; const double eps = 1e-10; typedef long long ll; typedef double db; template <class T> void read(T &x) { char c; bool op = 0; while(c = getchar(), c < ‘0‘ || c > ‘9‘) if(c == ‘-‘) op = 1; x = c - ‘0‘; while(c = getchar(), c >= ‘0‘ && c <= ‘9‘) x = x * 10 + c - ‘0‘; if(op) x = -x; } template <class T> void write(T x) { if(x < 0) putchar(‘-‘), x = -x; if(x >= 10) write(x / 10); putchar(‘0‘ + x % 10); } const int N = 1e5 + 5; struct node { int l,r,nxt; db w; }a[N]; int lst[N],len = 0; int n,m,judge = 0; void add(int x,int y,db w) { a[++len].l = x; a[len].r = y; a[len].w = w; a[len].nxt = lst[x]; lst[x] = len; } int vis[N]; db d[N]; void check(int now,db x) { vis[now] = 1; for(int k = lst[now];k;k = a[k].nxt) { int y = a[k].r; if(d[y] > d[now] + a[k].w - x) { if(vis[y] || judge) { judge = 1; break; } d[y] = d[now] + a[k].w - x; check(y,x); } } vis[now] = 0; } int main() { read(n);read(m); duke(i,1,m) { int x,y; db dis; read(x);read(y); scanf("%lf",&dis); add(x,y,dis); } db l = -1e6,r = 1e6; while(r - l > eps) { db mid = (l + r) / 2; clean(vis); clean(d); judge = 0; duke(i,1,n) { check(i,mid); if(judge) { break; } } if(judge) r = mid; else l = mid; } printf("%.8lf\n",l); return 0; }
P3199 [HNOI2009]最小圈 01分數規劃