[BZOJ4873][六省聯考2017]壽司餐廳(最大權閉合子圖)
阿新 • • 發佈:2018-03-28
矩陣 size problem fin rep min 現在 相互 情況
4873: [Shoi2017]壽司餐廳
Time Limit: 20 Sec Memory Limit: 512 MB
Submit: 490 Solved: 350
[Submit][Status][Discuss]Description
Kiana最近喜歡到一家非常美味的壽司餐廳用餐。每天晚上,這家餐廳都會按順序提供n種壽司,第i種壽司有一個 代號ai和美味度di,i,不同種類的壽司有可能使用相同的代號。每種壽司的份數都是無限的,Kiana也可以無限次 取壽司來吃,但每種壽司每次只能取一份,且每次取走的壽司必須是按餐廳提供壽司的順序連續的一段,即Kiana 可以一次取走第1,2種壽司各一份,也可以一次取走第2,3種壽司各一份,但不可以一次取走第1,3種壽司。由於餐 廳提供的壽司種類繁多,而不同種類的壽司之間相互會有影響:三文魚壽司和魷魚壽司一起吃或許會很棒,但和水 果壽司一起吃就可能會肚子痛。因此,Kiana定義了一個綜合美味度di,j(i<j),表示在一次取的壽司中,如果包含 了餐廳提供的從第i份到第j份的所有壽司,吃掉這次取的所有壽司後將獲得的額外美味度。由於取壽司需要花費一 些時間,所以我們認為分兩次取來的壽司之間相互不會影響。註意在吃一次取的壽司時,不止一個綜合美味度會被 累加,比如若Kiana一次取走了第1,2,3種壽司各一份,除了d1,3以外,d1,2,d2,3也會被累加進總美味度中。神奇 的是,Kiana的美食評判標準是有記憶性的,無論是單種壽司的美味度,還是多種壽司組合起來的綜合美味度,在 計入Kiana的總美味度時都只會被累加一次。比如,若Kiana某一次取走了第1,2種壽司各一份,另一次取走了第2,3 種壽司各一份,那麽這兩次取壽司的總美味度為d1,1+d2,2+d3,3+d1,2+d2,3,其中d2,2只會計算一次。奇怪的是, 這家壽司餐廳的收費標準很不同尋常。具體來說,如果Kiana一共吃過了c(c>0)種代號為x的壽司,則她需要為這些 壽司付出mx^2+cx元錢,其中m是餐廳給出的一個常數。現在Kiana想知道,在這家餐廳吃壽司,自己能獲得的總美 味度(包括所有吃掉的單種壽司的美味度和所有被累加的綜合美味度)減去花費的總錢數的最大值是多少。由於她 不會算,所以希望由你告訴她Input
第一行包含兩個正整數n,m,分別表示這家餐廳提供的壽司總數和計算壽司價格中使用的常數。 第二行包含n個正整數,其中第k個數ak表示第k份壽司的代號。 接下來n行,第i行包含n-i+1個整數,其中第j個數di,i+j-1表示吃掉壽司能 獲得的相應的美味度,具體含義見問題描述。 N<=100,Ai<=1000Output
輸出共一行包含一個正整數,表示Kiana能獲得的總美味度減去花費的總錢數的最大值。
Sample Input
3 1
2 3 2
5 -10 15
-10 15
15Sample Output
12
【樣例1說明】在這組樣例中,餐廳一共提供了3份壽司,它們的代號依次為a1=2,a2=3,a3=2,計算價格時的常數m=1。在保證每
次取壽司都能獲得新的美味度的前提下,Kiana一共有14種不同的吃壽司方案:
1.Kiana一個壽司也不吃,這樣她獲得的總美味度和花費的總錢數都是0,兩者相減也是0;
2.Kiana只取1次壽司,且只取第1個壽司,即她取壽司的情況為{[1,1]},這樣獲得的總美味度為5,花費的總錢數
為1-2^2+1*2=6,兩者相減為-1;
3.Kiana只取1次壽司,且只取第2個壽司,即她取壽司的情況為{[2,2]},這樣獲得的總美味度為-10,花費的總錢
數為1-3^2+1*3=12,兩者相減為-22;4.Kiana只取1次壽司,且只取第3個壽司,即她取壽司的情況為{[3,3]},這樣獲得的總美味度為15,花費的總錢數
為1*2^2+1*2=6,兩者相減為9;
5.Kiana只取1次壽司,且取第1,2個壽司,即她取壽司的情況為{[1,2]},這樣獲得的總美味度為5+(-10)+(-10)=-1
5,花費的總錢數為(1-2^2+1*2)+(1-3^2+1*3)=18,兩者相減為-33;
6.Kiana只取1次壽司,且取第2,3個壽司,即她取壽司的情況為{[2,3]},這樣獲得的總美味度為(-10)+15+15=20,
花費的總錢數為(1-2^2+1*2)+(1*3^2+1*3)=18,兩者相減為2;
7.Kiana只取1次壽司,且取第1,2,3個壽司,即她取壽司的情況為{[1,3]},這樣獲得的總美味度為5+(-10)+15+(-1
0)+15+15=30,花費的總錢數為(1*2^2+2*2)+(1*3^2+1*3)=20,兩者相減為10。
8.Kiana取2次壽司,第一次取第1個壽司,第二次取第2個壽司,即她取壽司的情況為{[1,1],[2,2]},這樣獲得的
總美味度為5+(-10)=-5,花費的總錢數為(1*2^2+1*2)+(1*3^2+1*3)=18,兩者相減為-23;
9.Kiana取2次壽司,第一次取第1個壽司,第二次取第3個壽司,即她取壽司的情況為{[1,1],[3,3]},這樣獲得的
總美味度為5+15=20,花費的總錢數為1*2^2+2*2=8,兩者相減為12;
10.Kiana取2次壽司,第一次取第2個壽司,第二次取第3個壽司,即她取壽司的情況為{[2,2],[3,3]},這樣獲得的
總美味度為(-10)+15=5,花費的總錢數為(1*2^2+1*2)+(1*3^2+1*3)=18,兩者相減為-13;
11.Kiana取2次壽司,第一次取第1,2個壽司,第二次取第3個壽司,即她取壽司的情況為{[1,2],[3,3]},這樣獲得
的總美味度為5+(-10)+(-10)+15=0,花費的總錢數為(1*2^2+2*2)+(1*3^2+1*3)=20,兩者相減為-20;
12.Kiana取2次壽司,第一次取第1個壽司,第二次取第2,3個壽司,即她取壽司的情況為{[1,1],[2,3]},這樣獲得
的總美味度為5+(-10)+15+15=25,花費的總錢數為(1-22+2-2)+(1-32+1-3)=20,兩者相減為5;
13.Kiana取2次壽司,第一次取第1,2個壽司,第二次取第2,3個壽司,即她取壽司的情況為{[1,2],[2,3]},這樣獲
得的總美味度為5+(-10)+15+(-10)+15=15,花費的總錢數為(1*2^2+2*2)+(1*3^2+1*3)=20,兩者相減為-5;
14.Kiana取3次壽司,第一次取第1個壽司,第二次取第2個壽司,第三次取第3個壽司,即她取壽司的情況為{[1,1]
,[2,2],[3,3]},這樣獲得的總美味度為5+(-10)+15=10,花費的總錢數為(1*2^2+2*2)+(1*3^2+1*3)=20,兩者相減
為-10。
所以Kiana會選擇方案9,這時她獲得的總美味度減去花費的總錢數的值最大為12。HINT
Source
黑吉遼滬冀晉六省聯考
[Submit][Status][Discuss]
挺簡單的最大權閉合子圖模型,我怎麽就沒有看出來呢?
首先將d[][]看成一個右上三角矩陣,那麽如果d[i][j]有貢獻,那麽d[i+1][j]和d[i][j-1]都必然有貢獻。
考慮付費情況,每個位置建一個點i‘,d[i][j]向i‘和j‘連邊,i‘,j‘ 向T連各自費用的邊。對於$mx^2$的部分,對每個編號再建一個新點bel,i‘向bel[a[i]]連邊。
#include<cstdio> #include<cstring> #include<algorithm> #define rep(i,l,r) for (int i=l; i<=r; i++) #define For(i,x) for (int i=h[x],k; i; i=nxt[i]) using namespace std; const int N=30100,M=2000100,inf=0x3f3f3f3f; int to[M],nxt[M],f[M],h[N],q[M],d[N],mp[110][110],id[110][110],bel[1010]; int n,m,S,T,ans,cnt=1,tot,a[N],vis[1010]; void add(int u,int v,int w){ to[++cnt]=v; nxt[cnt]=h[u]; f[cnt]=w; h[u]=cnt; to[++cnt]=u; nxt[cnt]=h[v]; f[cnt]=0; h[v]=cnt; } bool bfs(){ memset(d,0,sizeof(d)); q[1]=S; d[S]=1; for (int st=0,ed=1; st!=ed; ){ int x=q[++st]; For(i,x) if (!d[k=to[i]] && f[i]) d[k]=d[x]+1,q[++ed]=k; } return d[T]; } int dfs(int x,int lim){ if (x==T) return lim; int c=0; For(i,x) if (f[i] && d[k=to[i]]==d[x]+1){ int t=dfs(k,min(f[i],lim-c)); c+=t; f[i]-=t; f[i^1]+=t; if (c==lim) return lim; } if (!c) d[x]=-1; return c; } int dinic(){ int res=0; while (bfs()) res+=dfs(S,inf); return res;} void build(){ S=0; rep(i,1,n) rep(j,i,n) id[i][j]=++tot; rep(i,1,n) if (!vis[a[i]]) vis[a[i]]=1,bel[a[i]]=++tot; T=tot+n+1; memset(vis,0,sizeof(vis)); rep(i,1,n) if (!vis[a[i]]) vis[a[i]]=1,add(bel[a[i]],T,m*a[i]*a[i]); rep(i,1,n) add(tot+i,bel[a[i]],inf),add(tot+i,T,a[i]); rep(i,1,n) rep(j,i,n){ add(id[i][j],tot+i,inf),add(id[i][j],tot+j,inf); if (mp[i][j]>0) ans+=mp[i][j],add(S,id[i][j],mp[i][j]); else if (mp[i][j]<0) add(id[i][j],T,-mp[i][j]); if (i!=j) add(id[i][j],id[i+1][j],inf),add(id[i][j],id[i][j-1],inf); } } int main(){ freopen("sushi.in","r",stdin); freopen("sushi.out","w",stdout); scanf("%d%d",&n,&m); rep(i,1,n) scanf("%d",&a[i]); rep(i,1,n) rep(j,i,n) scanf("%d",&mp[i][j]); build(); printf("%d\n",ans-dinic()); return 0; }
[BZOJ4873][六省聯考2017]壽司餐廳(最大權閉合子圖)