比較複雜放LOJ題面好了qaq...php
Kiana 最近喜歡到一家很是美味的壽司餐廳用餐。c++
天天晚上,這家餐廳都會按順序提供 \(n\) 種壽司,第 \(i\) 種壽司有一個代號 \(a_i\) 和美味度 \(d_{i, i}\),不一樣種類的壽司有可能使用相同的代號。每種壽司的份數都是無限的,Kiana 也能夠無限次取壽司來吃,但每種壽司每次只能取一份,且每次取走的壽司必須是按餐廳提供壽司的順序連續的一段,即 Kiana 能夠一次取走第 \(1, 2\) 種壽司各一份,也能夠一次取走第 \(2, 3\) 種壽司各一份,但不能夠一次取走第 \(1, 3\) 種壽司。網絡
因爲餐廳提供的壽司種類繁多,而不一樣種類的壽司之間相互會有影響:三文魚壽司和魷魚壽司一塊兒吃或許會很棒,但和水果壽司一塊兒吃就可能會肚子痛。所以,Kiana 定義了一個綜合美味度 \(d_{i, j} \ (i < j)\),表示在一次取的壽司中,若是包含了餐廳提供的從第 \(i\) 份到第 \(j\) 份的全部壽司,吃掉此次取的全部壽司後將得到的額外美味度。因爲取壽司須要花費一些時間,因此咱們認爲分兩次取來的壽司之間相互不會影響。注意在吃一次取的壽司時,不止一個綜合美味度會被累加,好比若 Kiana 一次取走了第 \(1, 2, 3\) 種壽司各一份,除了 \(d_{1, 3}\) 之外,\(d_{1, 2}, d_{2, 3}\) 也會被累加進總美味度中。spa
神奇的是,Kiana 的美食評判標準是有記憶性的,不管是單種壽司的美味度,仍是多種壽司組合起來的綜合美味度,在計入 Kiana 的總美味度時都只會被累加一次。好比,若 Kiana 某一次取走了第 \(1, 2\) 種壽司各一份,另外一次取走了第 \(2, 3\) 種壽司各一份,那麼這兩次取壽司的總美味度爲 \(d_{1, 1} + d_{2, 2} + d_{3, 3} + d_{1, 2} + d_{2, 3}\),其中 \(d_{2, 2}\) 只會計算一次。rest
奇怪的是,這家壽司餐廳的收費標準很不一樣尋常。具體來講,若是 Kiana 一共吃過了 \(c \ (c > 0)\) 種代號爲 \(x\) 的壽司,則她須要爲這些壽司付出 \(mx^2 + cx\) 元錢,其中 \(m\) 是餐廳給出的一個常數。code
如今 Kiana 想知道,在這家餐廳吃壽司,本身能得到的總美味度(包括全部吃掉的單種壽司的美味度和全部被累加的綜合美味度)減去花費的總錢數的最大值是多少。因爲她不會算,因此但願由你告訴她。blog
\(n\le 100,a_i\le 1000,m\in\{0,1\}\)get
好像是個...裸的最大權閉合子圖...最大權閉合子圖都不知道果真是學了假的網絡流it
顯然選了一個區間後全部子區間也要選, 選了一個 \(d_{i,i}\) 後就要選花費點. 花費點能夠拆成兩部分, 一部分是 \(cx\) 直接從 \(d_{i,i}\) 裏減去就能夠了, 另外一部分是 \(mx^2\) 須要對於每個壽司代號都新建一個點來表達.class
而後它們之間的制約關係表達成有向邊, 求最大權閉合子圖就能夠了.
果真我仍是太菜了...
#include <bits/stdc++.h> const int MAXN=1e2+10; const int MAXV=1e4+10; const int MAXE=1e6+10; const int INF=0x7FFFFFFF; struct Edge{ int from; int to; int flow; Edge* rev; Edge* next; }; Edge E[MAXE]; Edge* head[MAXV]; Edge* cur[MAXV]; Edge* top=E; int n; int m; int a[MAXN]; bool vis[1010]; int depth[MAXV]; int id[MAXN][MAXN]; int val[MAXN][MAXN]; bool BFS(int,int); int Dinic(int,int); int DFS(int,int,int); void Insert(int,int,int); int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%d",a+i); int s=0,t=1; int cnt=1,sum=0; for(int i=1;i<=n;i++){ for(int j=i;j<=n;j++){ scanf("%d",val[i]+j); id[i][j]=++cnt; if(i==j) val[i][j]-=a[i]; if(val[i][j]>=0){ sum+=val[i][j]; Insert(s,id[i][j],val[i][j]); } else Insert(id[i][j],t,-val[i][j]); } } for(int i=1;i<=n;i++){ for(int j=i+1;j<=n;j++){ Insert(id[i][j],id[i+1][j],INF); Insert(id[i][j],id[i][j-1],INF); } } for(int i=1;i<=n;i++) Insert(id[i][i],cnt+a[i],INF); for(int i=1;i<=n;i++){ if(!vis[a[i]]){ vis[a[i]]=true; Insert(cnt+a[i],t,m*a[i]*a[i]); } } printf("%d\n",sum-Dinic(s,t)); return 0; } int Dinic(int s,int t){ int ans=0; while(BFS(s,t)) ans+=DFS(s,INF,t); return ans; } bool BFS(int s,int t){ memset(depth,0,sizeof(depth)); std::queue<int> q; q.push(s); depth[s]=1; cur[s]=head[s]; while(!q.empty()){ s=q.front(); q.pop(); for(Edge* i=head[s];i!=NULL;i=i->next){ if(i->flow>0&&depth[i->to]==0){ depth[i->to]=depth[s]+1; cur[i->to]=head[i->to]; if(i->to==t) return true; q.push(i->to); } } } return false; } int DFS(int s,int flow,int t){ if(s==t||flow<=0) return flow; int rest=flow; for(Edge*& i=cur[s];i!=NULL;i=i->next){ if(i->flow>0&&depth[i->to]==depth[s]+1){ int tmp=DFS(i->to,std::min(rest,i->flow),t); if(tmp<=0) depth[i->to]=0; rest-=tmp; i->flow-=tmp; i->rev->flow+=tmp; if(rest<=0) break; } } return flow-rest; } inline void Insert(int from,int to,int flow){ top->from=from; top->to=to; top->flow=flow; top->rev=top+1; top->next=head[from]; head[from]=top++; top->from=to; top->to=from; top->flow=0; top->rev=top-1; top->next=head[to]; head[to]=top++; }