bzoj1449 JSOI2009 球隊收益

2022-06-03 11:36:11 字數 1698 閱讀 4463

乙個整數表示聯盟裡所有球隊收益之和的最小值。

3 31 0 2 1

1 1 10 1

0 1 3 3

1 22 3

3 143

題解:這道題可以像wc2007石頭剪刀布那樣由s向每場比賽連一條容量為1費用為0的邊,由每場比賽向兩個人分別連容量為1費用為0的邊

現在要處理每個人如何向t連邊

假設i號隊伍贏了x場輸了y場,假如將i號隊輸了的某局改為i號隊贏了,那麼收益變化了c(x+1)2+d(y-1)2-cx2-dy2=2cx-2dy+c+d

設i號隊將要參加的比賽數為rest[i]

我們先假設i隊未確定的比賽都輸了,那麼由i號隊向t連rest條邊,容量均為1,費用分別為 2c*win[i]-2d*(lose[i]+rest[i])+c+d , 2c*(win[i]+1)-2d*(lose[i]+rest[i]-1)+c+d , ... , 2c*(win[i]+rest[i])-2d*lose[i]+c+d

答案就是初始收益(假設了未確定的比賽都輸了)+ 最小費用最大流的費用

code:

1 #include2 #include3 #include4 #include5 #include6

#define maxn 6005

7#define maxm 20000

8#define inf 1061109567

9using

namespace

std;

10char

ch;11

bool

ok;12

void read(int &x)

17int n,m,a[1005],b[1005],ans,win[5005],lose[5005],rest[5005],c[5005],d[5005

];18

struct

costflow

23void put(int a,int b,int c,int d)

24void add(int a,int b,int c,int d)

25void

spfa()39}

40 bo[u]=0;41

}42}43

int dfs(int u,int rest,int

totval)

46int ans=0;47

for (int p=now[u],v=son[p];p&&rest;p=pre[p],v=son[p])

48if (val[p]&&!bo[v]&&dis[v]==dis[u]+cost[p])

52return

ans;53}

54bool

relax()

63void

work()while

(tmp);

70 }while

(relax());71}

72}f;

73int

main()

82for (int i=1;i<=m;i++) f.add(f.s,n+i,1,0),f.add(n+i,a[i],1,0),f.add(n+i,b[i],1,0

);83

f.work();

84 printf("

%d\n

",ans+f.totcost);

85return0;

86 }

JSOI2009 bzoj1449 球隊收益

description input output 乙個整數表示聯盟裡所有球隊收益之和的最小值。首先假設全輸,然後給每場比賽分配乙個贏家,每個隊伍每多贏一場多獲得的收益作為費用。但是有乙個問題,如何保證每次走的是對應的邊?也就是,如何保證贏第一場的時候增加的收益是贏一場減贏零場,而不是贏兩場減贏一場?...

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...