description input output 乙個整數表示聯盟裡所有球隊收益之和的最小值。首先假設全輸,然後給每場比賽分配乙個贏家,每個隊伍每多贏一場多獲得的收益作為費用。
但是有乙個問題,如何保證每次走的是對應的邊?也就是,如何保證贏第一場的時候增加的收益是贏一場減贏零場,而不是贏兩場減贏一場?可以發現,假設當前贏了
x 場輸了
y場,多贏一場的收益是2c
ix−2
diy+
ci+d
i ,
x 越大,
y越小,上式越大。因此每次一定優先走
x 比較小的邊。
#include
#include
#include
using namespace std;
const int
s=6005,t=6006,oo=0x3f3f3f3f,mod=6007;
int fir[6010],ne[200010],to[200010],w[200010],c[200010],
que[6010],in[6010],minw[6010],len[6010],fa[6010],
cnt[5010],ci[5010],di[5010],win[5010],lose[5010],
n,m,num,ans;
void add(int u,int v,int
x,int
y)int main()
for (int i=1;i<=n;i++)
for (int j=1;j<=cnt[i];j++)
add(i,t,1,ci[i]*(win[i]+j)*(win[i]+j)+di[i]*(lose[i]+cnt[i]-j)*(lose[i]+cnt[i]-j)
-ci[i]*(win[i]+j-1)*(win[i]+j-1)-di[i]*(lose[i]+cnt[i]-j+1)*(lose[i]+cnt[i]-j+1));
for (int i=1;i<=n;i++) ans+=ci[i]*win[i]*win[i]+di[i]*(lose[i]+cnt[i])*(lose[i]+cnt[i]);
while (1)
}in[u]=0;
}if (!minw[t]) break;
ans+=minw[t]*len[t];
for (int i=fa[t];i;i=fa[to[i^1]])
}printf("%d\n",ans);
}
bzoj1449 JSOI2009 球隊收益
傳送門 感覺就是費用流呀。可以發現這道題與之前的費用流題有所不同,因為乙個球隊不論輸還是贏都會獲得收益。這裡就要用到乙個技巧,我們可以假裝比賽雙方都輸,然後修改贏的就ok辣。然後就是每個人向終點連邊,這裡的費用隨著流量的變化而變化,所以我們要用到拆邊法。考慮乙個人從贏win i 次 輸lose i ...
BZOJ1449 JSOI2009 球隊收益
bzoj luogu 在乙個籃球聯賽裡,有 n 支球隊,球隊的支出是和他們的勝負場次有關係的,具體來說,第i支球隊的賽季總支出是 c i times x 2 d i times y 2,d i le c i 其中 x,y 分別表示這只球隊本賽季的勝負場次。現在賽季進行到了一半,每只球隊分別取得了 a...
bzoj1449 JSOI2009 球隊收益
time limit 5 sec memory limit 64 mb submit 1131 solved 640 submit status discuss 乙個整數表示聯盟裡所有球隊收益之和的最小值。3 31 0 2 1 1 1 10 1 0 1 3 3 1 22 3 3 143 分析 很妙的...