【bzoj1690/Usaco2007 Dec】奶牛的旅行——分數規劃 最優比率環
Description
作為對奶牛們辛勤工作的回報,Farmer John決定帶她們去附近的大城市玩一天。旅行的前夜,奶牛們在興奮地討論如何最好地享受這難得的閑暇。 很幸運地,奶牛們找到了一張詳細的城市地圖,上面標註了城市中所有L(2 <= L <= 1000)座標誌性建築物(建築物按1..L順次編號),以及連接這些建築物的P(2 <= P <= 5000)條道路。按照計劃,那天早上Farmer John會開車將奶牛們送到某個她們指定的建築物旁邊,等奶牛們完成她們的整個旅行並回到出發點後,將她們接回農場。由於大城市中總是寸土寸金,所有的道路都很窄,政府不得不把它們都設定為通行方向固定的單行道。 盡管參觀那些標誌性建築物的確很有意思,但如果你認為奶牛們同樣享受穿行於大城市的車流中的話,你就大錯特錯了。與參觀景點相反,奶牛們把走路定義為無趣且令她們厭煩的活動。對於編號為i的標誌性建築物,奶牛們清楚地知道參觀它能給自己帶來的樂趣值F_i (1 <= F_i <= 1000)。相對於奶牛們在走路上花的時間,她們參觀建築物的耗時可以忽略不計。 奶牛們同樣仔細地研究過城市中的道路。她們知道第i條道路兩端的建築物 L1_i和L2_i(道路方向為L1_i -> L2_i),以及她們從道路的一頭走到另一頭所需要的時間T_i(1 <= T_i <= 1000)。 為了最好地享受她們的休息日,奶牛們希望她們在一整天中平均每單位時間內獲得的樂趣值最大。當然咯,奶牛們不會願意把同一個建築物參觀兩遍,也就是說,雖然她們可以兩次經過同一個建築物,但她們的樂趣值只會增加一次。順便說一句,為了讓奶牛們得到一些鍛煉,Farmer John要求奶牛們參觀至少2個建築物。 請你寫個程序,幫奶牛們計算一下她們能得到的最大平均樂趣值。
Input
* 第1行: 2個用空格隔開的整數:L 和 P
* 第2..L+1行: 第i+1行僅有1個整數:F_i * 第L+2..L+P+1行: 第L+i+1行用3個用空格隔開的整數:L1_i,L2_i以及T_i, 描述了第i條道路。
Output
* 第1行: 輸出1個實數,保留到小數點後2位(直接輸出,不要做任何特殊的取 整操作),表示如果奶牛按題目中描述的一系列規則來安排她們的旅 行的話,她們能獲得的最大平均樂趣值
Sample Input
5 730
10
10
5
10
1 2 3
2 3 2
3 4 5
3 5 2
4 5 5
5 1 3
5 2 2
Sample Output
6.00分析: 首先分析最優解必然為一個單獨的環(一定不會是環套環),為什麽?我不知道,自己推一下吧...... 這樣的話我們把邊的利潤定義為邊指向的點i的利潤e[i],把邊的代價定義為指向的那個點的代價v[i],每個點選或不選的情況定義為x[i]。 這樣就把利潤和代價都放在了邊上。 定義一個函數f(l)=l*sigma(v[i]*x[i])-sigma(e[i]*x[i])=sigma((l*v[i]-e[i])*x[i]),令d[i]=l*v[i]-e[i]。 當f(l)<0時,l*sigma(v[i]*x[i])-sigma(e[i]*x[i])<0,即sigma(e[i]*x[i])/sigma(v[i]*x[i])>l,表明當前的選取方式能得到比當前l更大的解;
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #define mem(a) memset(a,0,sizeof(a)) 5 const int N=1005,P=5005; 6 const double eps=1e-7; 7 int n,m,tot=0,first[N],a[N]; 8 double d[N]; 9 bool flag,ok[N]; 10 struct node{ 11 int ne,to,w; 12 double v; 13 }e[P*2]; 14 int read(){ 15 int ans=0,f=1;char c=getchar(); 16 while(c<‘0‘||c>‘9‘){if(c==‘-‘)f=-1;c=getchar();} 17 while(c>=‘0‘&&c<=‘9‘){ans=ans*10+c-48;c=getchar();} 18 return ans*f; 19 } 20 void add(int u,int v,int w){ 21 e[++tot]=(node){first[u],v,w,0};first[u]=tot; 22 } 23 void dfs(int x){ 24 ok[x]=1; 25 for(int i=first[x];i;i=e[i].ne){ 26 int to=e[i].to; 27 if(d[to]>d[x]+e[i].v){ 28 if(ok[to]){flag=1;return;} 29 d[to]=d[x]+e[i].v; 30 dfs(to); 31 } 32 } 33 ok[x]=0; 34 } 35 bool check(double x){ 36 flag=0; 37 for(int i=1;i<=n;i++)ok[i]=d[i]=0; 38 for(int i=1;i<=n;i++){dfs(i);if(flag)return 1;} 39 return 0; 40 } 41 int main(){ 42 n=read();m=read(); 43 for(int i=1;i<=n;i++)a[i]=read(); 44 for(int j=1,uu,vv,z;j<=m;j++){ 45 uu=read();vv=read();z=read(); 46 add(uu,vv,z); 47 } 48 double l=0,r=1000.0,mid; 49 while(r-l>eps){ 50 mid=(l+r)/2.0; 51 for(int i=1;i<=n;i++){ 52 for(int j=first[i];j;j=e[j].ne){ 53 e[j].v=mid*e[j].w-a[e[j].to]; 54 } 55 } 56 if(check(mid))l=mid; 57 else r=mid; 58 } 59 printf("%.2f",mid); 60 return 0; 61 }bzoj1690
【bzoj1690/Usaco2007 Dec】奶牛的旅行——分數規劃 最優比率環