zoukankan      html  css  js  c++  java
  • BZOJ4873 LuoguP3749 寿司餐厅

    题面太长,请诸位自行品尝—>寿司餐厅

     

    分析:

      首先题目中给了限制条件,假如选了D(i,j)(i<j),那么也就选了D(i+1,j)和D(i,j-1)两个点。

      于是我们一下就明白了,哦,最大权闭合子图~

      所以我们让每一个D代表一个点,然后对于每个D(i,j)代表的点,分别向D(i+1,j)和D(i,j-1)所代表的点连边(容量为inf),然后按照最大权闭合子图的建图方式建图~

      完了?

      并没有。我们接着看题面,其实代价还有一个,是mx^2+cx,这个我们怎么加上?

      直接看啥也看不出来,所以我们拆开来看。首先,mx^2是由代号和常数m决定的,所以我们可以把它独立开来,对每个编号建立一个点,因为它是代价,所以点权是负的,所以我们从它向汇点T连一条边权为mx^2的边,然后把每个代号为x的寿司向它代号那个点连边。

      再考虑cx怎么计算,这个好办,多选一种编号为x的寿司就会产生x的代价,所以我们把每种寿司向T点连边,容量为x即可产生费用。

    代码:

     1 #include<bits/stdc++.h>
     2 #define ms(a,x) memset(a,x,sizeof(a))
     3 #define p(x,y) ((x-1)*n+y+1000)
     4 using namespace std;int S,T,tot;
     5 const int N=40000,inf=0x3f3f3f3f;
     6 struct node{int y,z,nxt;}e[N*64];int a[N];
     7 int c=1,h[N],d[N],m,k,n,ans,q[N],sn[N],g,sm;
     8 void add(int x,int y,int z){
     9     e[++c]=(node){y,z,h[x]};h[x]=c;
    10     e[++c]=(node){x,0,h[y]};h[y]=c;
    11 } bool bfs(){int f=1,t=0;ms(d,-1);
    12     d[S]=0;q[++t]=S;
    13     while(f<=t){
    14         int x=q[f++];
    15         for(int i=h[x],y;i;i=e[i].nxt)
    16         if(d[y=e[i].y]==-1&&e[i].z)
    17         d[y]=d[x]+1,q[++t]=y;
    18     } return (d[T]!=-1);
    19 } int dfs(int x,int f){
    20     if(x==T) return f;int w,tmp=0;
    21     for(int i=h[x],y;i;i=e[i].nxt)
    22     if(d[y=e[i].y]==d[x]+1&&e[i].z){
    23         w=dfs(y,min(e[i].z,f-tmp));
    24         if(!w) d[y]=-1;e[i].z-=w;
    25         e[i^1].z+=w;tmp+=w;if(tmp==f) return f;
    26     } return tmp;
    27 } void solve(){
    28     while(bfs()) tot+=dfs(S,inf);
    29 } int main(){
    30     scanf("%d%d",&n,&m);S=0;T=n*n+1001;
    31     for(int i=1;i<=n;i++){
    32         scanf("%d",&a[i]);
    33         if(m&&!sn[a[i]])
    34         sn[a[i]]=1,add(a[i],T,a[i]*a[i]);
    35         add(p(i,i),a[i],inf);
    36         add(p(i,i),T,a[i]);
    37     } for(int i=1;i<=n;i++)
    38     for(int j=i;j<=n;j++){
    39         scanf("%d",&g);sm+=(g>0?g:0);
    40         if(g>0) add(S,p(i,j),g);
    41         else add(p(i,j),T,-g);
    42         if(i!=j) add(p(i,j),p(i+1,j),inf);
    43         if(i!=j) add(p(i,j),p(i,j-1),inf);
    44     } solve();printf("%d
    ",sm-tot);return 0;
    45 }
    最大权闭合子图
  • 相关阅读:
    蓝盾杯writeup
    记一次被吊打的排位赛(writeup)
    记一次简单的PHP代码审计(SSRF案例)
    记一次简单的GetShell案例
    斯坦福cs231n计算机视觉经典课程笔记(更新中)
    centos8 下配置 uwsgi + Django
    C++坑点随笔
    matlab调教日记 ---- 语法问题汇总
    matlab调教日记 --- debug篇
    MySQL解决中文编码问题
  • 原文地址:https://www.cnblogs.com/Alan-Luo/p/10256251.html
Copyright © 2011-2022 走看看