BZOJ_4873_[Shoi2017]寿司餐厅_最大权闭合子图

题意:http://www.lydsy.com/JudgeOnline/problem.php?id=4873

分析:我们发现分数正负都有,并且之间有依赖关系,很容易想到最大权闭合子图。

建图:

1.S向正点连边,负点向T连边。

2.选了[i~j]显然要选[i+1~j]和[i~j-1],分别连边。

3.对于i==j的点,向对应的寿司连边。

4.总花费m*x*x+c*x拆成两部分。对于每个代号x,向T连容量为m*x*x的边,c*x这部分我们考虑算f[i][i]时把f[i][i]的值减掉x,当然也可以每个寿司向T连容量为x的边。

完了。

代码:

 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <algorithm>
 4 #include <queue>
 5 using namespace std;
 6 #define inf 100000000
 7 #define LL long long
 8 #define S (30000)
 9 #define T (30001)
10 int d[110][110],n,m;
11 int head[31000],to[4000000],nxt[4000000],cnt=1;
12 int dep[31000],a[110],tot,idx[110][110],mxn;
13 LL flow[4000000],sum;
14 inline void add(int u,int v,LL f)
15 {
16     to[++cnt]=v;nxt[cnt]=head[u];head[u]=cnt;flow[cnt]=f;
17     to[++cnt]=u;nxt[cnt]=head[v];head[v]=cnt;flow[cnt]=0;
18 }
19 bool bfs()
20 {
21     queue <int> q;
22     memset(dep,0,sizeof(dep));
23     dep[S]=1;q.push(S);
24     while(!q.empty())
25     {
26         int x=q.front();q.pop();
27         for(int i=head[x];i;i=nxt[i])
28         {
29             if(!dep[to[i]]&&flow[i])
30             {
31                 dep[to[i]]=dep[x]+1;
32                 if(to[i]==T)return 1;
33                 q.push(to[i]);
34             }
35         }
36     }
37     return 0;
38 }
39 LL dfs(int x,LL mf)
40 {
41     if(x==T)return mf;
42     LL nf=0;
43     for(int i=head[x];i;i=nxt[i])
44     {
45         if(dep[to[i]]==dep[x]+1&&flow[i])
46         {
47             int tmp=dfs(to[i],min(flow[i],mf-nf));
48             nf+=tmp;
49             flow[i]-=tmp;
50             flow[i^1]+=tmp;
51             if(nf==mf)break;
52         }
53     }
54     dep[x]=0;
55     return nf;
56 }
57 void dinic()
58 {
59     LL f;
60     while(bfs())
61     {
62         while(f=dfs(S,inf))
63             sum-=f;
64     }
65     printf("%lld",sum);
66 }
67 int main()
68 {
69     register int i,j;
70     scanf("%d%d",&n,&m);
71     for(i=1;i<=n;i++)
72         for(j=i;j<=n;j++)
73             idx[i][j]=++tot;
74     for(i=1;i<=n;i++)scanf("%d",&a[i]),mxn=max(mxn,a[i]);
75     for(i=1;i<=mxn;i++)add(tot+i,T,m*i*i);
76     for(i=1;i<=n;i++)add(idx[i][i],tot+a[i],inf);
77     for(i=1;i<=n;i++)
78     {
79         for(j=i;j<=n;j++)
80         {
81             scanf("%d",&d[i][j]);
82             if(i==j)d[i][j]-=a[i];
83             else{
84                 add(idx[i][j],idx[i+1][j],inf);
85                 add(idx[i][j],idx[i][j-1],inf);
86             }
87             if(d[i][j]>0)
88             {
89                 sum+=d[i][j];
90                 add(S,idx[i][j],d[i][j]);
91             }
92             else{
93                 add(idx[i][j],T,-d[i][j]);
94             }
95         }
96     }
97     dinic();
98 }

原文地址:https://www.cnblogs.com/suika/p/8456939.html

时间: 2024-08-26 23:24:25

BZOJ_4873_[Shoi2017]寿司餐厅_最大权闭合子图的相关文章

BZOJ 4873 [Shoi2017]寿司餐厅 | 网络流 最大权闭合子图

链接 BZOJ 4873 题解 当年的省选题--还记得蒟蒻的我Day1 20分滚粗-- 这道题是个最大权闭合子图的套路题.严重怀疑出题人就是先画好了图然后照着图编了个3000字的题面.和我喜欢的妹子当年给别人写的情书一样长-- 最大权闭合子图 最大权闭合子图问题:一个有向图中,每个点带有一个权值(有正有负),有向边\(u \to v\)表示选\(u\)必须选\(v\),选出一些点使权值和最大,问权值和最大是多少. 最大权闭合子图的解法:网络流建图,对于每个点\(u\),设权值为\(w_u\),如

BZOJ 4873 寿司餐厅(最大权闭合图 网络流)

寿司餐厅 时间限制: 1 Sec  内存限制: 512 MB提交: 6  解决: 3[提交][状态][讨论版] 题目描述 Kiana 最近喜欢到一家非常美味的寿司餐厅用餐.每天晚上,这家餐厅都会按顺序提供n种寿司,第i种寿司有一个代号 ai和美味度 di,i,不同种类的寿司有可能使用相同的代号.每种寿司的份数都是无限的,Kiana 也可以无限次取寿司来吃,但每种寿司每次只能取一份,且每次取走的寿司必须是按餐厅提供寿司的顺序连续的一段,即 Kiana 可以一次取走第 1,2种寿司各一份,也可以一次

BZOJ_3996_[TJOI2015]线性代数_最大权闭合子图

Description 给出一个N*N的矩阵B和一个1*N的矩阵C.求出一个1*N的01矩阵A.使得 D=(A*B-C)*A^T最大.其中A^T为A的转置.输出D Input 第一行输入一个整数N,接下来N行输入B矩阵,第i行第J个数字代表Bij. 接下来一行输入N个整数,代表矩阵C.矩阵B和矩阵C中每个数字都是不超过1000的非负整数. Output 输出最大的D Sample Input 3 1 2 1 3 1 0 1 2 3 2 3 7 Sample Output 2 HINT 1<=N<

【暖*墟】#网络流# 最大权闭合子图

[相关概念详解] 闭合图:有向图的一个点集,且这个点集的所有出边仍然指向该点集. 最大权闭合图:(每一个点有一个权值)在所有的合法闭合图中,点权之和最大的图. 处理问题:权值有正有负,重复选只算一次,选择有相互关联性 的问题. 首先有一个有向连通图(闭合图),每个点带有一个权值,例如: 造出一个超级源点S和一个超级汇点T,把S连边到所有带有正权的点上,每条边的容量是这个点的权: 把所有带负权的点连边到T,每条边的容量是这个点的权的相反数(正值).原来的边的容量设成无限大. 所有的点按权值的正负连

【最大权闭合子图】bzoj4873: [Shoi2017]寿司餐厅

为什么跑得这么慢 Description Kiana最近喜欢到一家非常美味的寿司餐厅用餐.每天晚上,这家餐厅都会按顺序提供n种寿司,第i种寿司有一个 代号ai和美味度di,i,不同种类的寿司有可能使用相同的代号.每种寿司的份数都是无限的,Kiana也可以无限次 取寿司来吃,但每种寿司每次只能取一份,且每次取走的寿司必须是按餐厅提供寿司的顺序连续的一段,即Kiana 可以一次取走第1,2种寿司各一份,也可以一次取走第2,3种寿司各一份,但不可以一次取走第1,3种寿司.由于餐 厅提供的寿司种类繁多,

BZOJ:4873: [Shoi2017]寿司餐厅

4873: [Shoi2017]寿司餐厅 首先很开心在膜你赛的时候做了出来. 看到数据范围,看到不能dp,看到贡献去重后计算,咦,流? 那就容易了,转最大权闭合子图,每个区间建一个点,取了就一定要取他的子区间(依赖关系),代价上也很容易用依赖关系搞. 提交完A了就没理,后来同学说我#1了??? #include<cstdio> #include<algorithm> #define MN 40001 using namespace std; int read_p,read_ca,r

b2OJ_1565_[NOI2009]植物大战僵尸_拓扑排序+最大权闭合子图

b2OJ_1565_[NOI2009]植物大战僵尸_拓扑排序+最大权闭合子 题意:n*m个植物,每个植物有分数(可正可负),和能保护植物的位置.只能从右往左吃,并且不能吃正被保护着的,可以一个不吃,求获得的最大分数. 分析:把每个植物向能保护它的植物连边.源点连正权点,负权点连汇点. 考虑在一个环上的植物是吃不到的,我们可以用拓扑排序确定哪些是能吃的. 然后求一遍最大权闭合子图就是答案. 代码: 1 #include <stdio.h> 2 #include <string.h>

bzoj4873: [Shoi2017]寿司餐厅(最小割)

传送门 大佬们是怎么一眼看出这是一个最大权闭合子图的……大佬好强->这里 1.把所有区间$(i,j)$看成一个点,如果权值大于0,则从$S$向他连边,容量为权值,否则从它向$T$连边,容量为权值的相反数 2.对于区间$(i,j)$,向所有的寿司$i$到$j$连边,表示选这个区间这些寿司必须选 3.对每一个寿司类型$w[i]$,为他们各自开一个点,向$T$连边,容量为$m*w[i]*w[i]$ 4.对每一个寿司向他们所属的类型$w[i]$连边,容量为$inf$,向$T$连边,容量为$w[i]$ 5

bzoj4873 [Shoi2017]寿司餐厅

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=4873 [题解] 没看出来是最大权闭合子图模型--要多学习学习qwq 首先区间$[i,j]$依赖于区间$[i+1,j]$和$[i,j-1]$.每个区间$[i,j](i < j)$的权值就是$d_{i,j}$. 特别地,区间$[i, i]$的权值为$d_{i,j} - a_i$(由于花费原因). 区间$[i, i]$还依赖于$a_i$这个点,$a_i$这个点的权值为$-m * a_i * a_