解题:六省联考 2017 寿司餐厅

题面

短神当时在考场上一眼把这个题秒了,然后吐槽说THU是不是都喜欢把最水的放在第三道=。=???

不愧是大爷orz

可以看出来是最大权闭合子图,问题是怎么建边(废话)

把每个区间看成一个点,每种寿司看成一个点

1.首先是最大权闭合子图的标准连法,对区间连,不说了

2.区间具有包含关系,所以$(i,j)(i!=j)$向$(i+1,j)$和$(i,j-1)$连边,流量为无穷大

3.每种寿司向汇点连$mx^2$的边

4.每个寿司(即$(i,i)$这种区间)向对应的寿司种类连边

5.每个寿司向汇点连x的边

注意就是网络流求最小割的时候和式要拆开连,连成一条链就成了取最小的一项了

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 const int B=110,N=12000,M=32000,inf=1e9;
 6 int p[N],noww[2*M],goal[2*M],flow[2*M];
 7 int num[B],val[B][B],idx[B][B],lnk[N];
 8 int pp[N],dep[N],que[N];
 9 int n,m,s,t,f,b,cnt,tot,ans;
10 void Link(int f,int t,int v)
11 {
12     noww[++cnt]=p[f],p[f]=cnt;
13     goal[cnt]=t,flow[cnt]=v;
14     noww[++cnt]=p[t],p[t]=cnt;
15     goal[cnt]=f,flow[cnt]=0;
16 }
17 void Init(int st,int ed)
18 {
19     for(int i=1;i<=ed;i++) pp[i]=p[i];
20     memset(dep,-1,sizeof dep);
21     que[f=b=0]=st,dep[st]=0;
22 }
23 bool Layering(int st,int ed)
24 {
25     Init(st,ed);
26     while(f<=b)
27     {
28         int tn=que[f++];
29         for(int i=pp[tn];i;i=noww[i])
30             if(flow[i]&&dep[goal[i]]==-1)
31                 dep[goal[i]]=dep[tn]+1,que[++b]=goal[i];
32     }
33     return ~dep[ed];
34 }
35 int Augmenting(int nd,int ed,int mn)
36 {
37     if(nd==ed||!mn)
38         return mn;
39     int tmp,tep=0;
40     for(int i=pp[nd];i;i=noww[i])
41     {
42         pp[nd]=i;
43         if(dep[goal[i]]==dep[nd]+1)
44             if(tmp=Augmenting(goal[i],ed,min(mn,flow[i])))
45             {
46                 flow[i]-=tmp,mn-=tmp;
47                 flow[i^1]+=tmp,tep+=tmp;
48                 if(!mn) break;
49             }
50     }
51     return tep;
52 }
53 void Dinic_Maxflow(int st,int ed)
54 {
55     while(Layering(st,ed))
56         ans-=Augmenting(st,ed,inf);
57 }
58 int main()
59 {
60     scanf("%d%d",&n,&m);
61     for(int i=1;i<=n;i++)
62         scanf("%d",&num[i]);
63     for(int i=1;i<=n;i++)
64         for(int j=i;j<=n;j++)
65             scanf("%d",&val[i][j]),idx[i][j]=++tot;
66     s=n*(n+1)/2+1001,t=s+1,cnt=1;
67     for(int i=1;i<=n;i++)
68         for(int j=i;j<=n;j++)
69         {
70             if(i!=j) 
71             {
72                 Link(idx[i][j],idx[i+1][j],inf);
73                 Link(idx[i][j],idx[i][j-1],inf);
74             }
75             if(val[i][j]<0) Link(idx[i][j],t,-val[i][j]);
76             else Link(s,idx[i][j],val[i][j]),ans+=val[i][j];
77         }
78     for(int i=1;i<=n;i++)    
79     {
80         Link(idx[i][i],t,num[i]),Link(idx[i][i],tot+num[i],inf);
81         if(!lnk[num[i]]) Link(tot+num[i],t,m*num[i]*num[i]),lnk[num[i]]=true;
82     }
83     Dinic_Maxflow(s,t),printf("%d",ans);
84     return 0;
85 }
View Code
原文地址:https://www.cnblogs.com/ydnhaha/p/10252024.html