bzoj4873: [Shoi2017]寿司餐厅
Posted CHerish_OI
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj4873: [Shoi2017]寿司餐厅相关的知识,希望对你有一定的参考价值。
4873: [Shoi2017]寿司餐厅
大难题啊啊!!!
题目:传送门
题解:一眼题是网络流,但还是不会OTZ,菜啊...
%题解...
最大权闭合子图!!!
好的...开始花式建边:
1、对于每个区间,我们把它看成一个点,按照权值正负连接源点或汇点(最大权闭合子图的套路)
2、对于所有的寿司类型k[i],各自开一个点,向ed连边,流量为m*k[i]*k[i];
3、对于1~n的每个寿司,向它的所属类型连边,流量为无限大;再向ed连边,流量为e[i]。
4、对于所有的区间i~j,向(i+1,j)和(i,j-1)连边,因为区间具有包含性。
WA了...再%题解...
漏了第五种情况:
5、对于所有区间,向区间内所有的点连边,流量为无限大,表示必须选对应的寿司才能选这个区间QWQ
跑网络流。。。
蒟蒻的代码(丑的一匹,慎点):
1 #include<cstdio> 2 #include<cstring> 3 #include<cstdlib> 4 #include<cmath> 5 #include<algorithm> 6 #define qread(x)x=read(); 7 using namespace std; 8 typedef long long LL; 9 inline int read() 10 { 11 int f=1,x=0;char ch; 12 while(ch<‘0‘ || ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();} 13 while(ch>=‘0‘ && ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();} 14 return f*x; 15 } 16 struct node 17 { 18 int x,y,c,next,other; 19 }a[2110000];int last[1110000],len; 20 int st,ed,n,m; 21 void ins(int x,int y,int c) 22 { 23 int k1,k2; 24 len++;k1=len; 25 a[len].x=x;a[len].y=y;a[len].c=c; 26 a[len].next=last[x];last[x]=len; 27 28 len++;k2=len; 29 a[len].x=y;a[len].y=x;a[len].c=0; 30 a[len].next=last[y];last[y]=len; 31 32 a[k1].other=k2; 33 a[k2].other=k1; 34 } 35 int list[11000],h[11000]; 36 int head,tail; 37 bool bfs() 38 { 39 memset(h,0,sizeof(h));h[st]=1; 40 list[1]=st;head=1;tail=2; 41 while(head!=tail) 42 { 43 int x=list[head]; 44 for(int k=last[x];k;k=a[k].next) 45 { 46 int y=a[k].y; 47 if(h[y]==0 && a[k].c>0) 48 { 49 h[y]=h[x]+1; 50 list[tail++]=y; 51 } 52 } 53 head++; 54 } 55 if(h[ed]>0)return true; 56 return false; 57 } 58 int findflow(int x,int flow) 59 { 60 if(x==ed)return flow; 61 int s=0,t; 62 for(int k=last[x];k;k=a[k].next) 63 { 64 int y=a[k].y; 65 if(h[y]==h[x]+1 && a[k].c>0 && flow>s) 66 { 67 t=findflow(y,min(a[k].c,flow-s)); 68 s+=t; 69 a[k].c-=t;a[a[k].other].c+=t; 70 } 71 } 72 if(s==0)h[x]=0; 73 return s; 74 } 75 int e[110]; 76 int d[110][110]; 77 int id1[110][110],id2[1100]; 78 bool v[1100]; 79 int jb() 80 { 81 memset(v,false,sizeof(v)); 82 LL sum=0,cnt=0; 83 for(int i=1;i<=n;i++) 84 for(int j=i;j<=n;j++) 85 id1[i][j]=++cnt; 86 87 for(int i=1;i<=n;i++) 88 if(v[e[i]]==0) 89 { 90 v[e[i]]=true; 91 id2[e[i]]=++cnt; 92 } 93 94 ed=cnt+n+1; 95 memset(v,false,sizeof(v)); 96 for(int i=1;i<=n;i++) 97 if(v[e[i]]==0) 98 { 99 v[e[i]]=true; 100 ins(id2[e[i]],ed,m*e[i]*e[i]);//种类的花费,和ed连边 101 } 102 for(int i=1;i<=n;i++) 103 { 104 ins(cnt+i,id2[e[i]],999999999); 105 ins(cnt+i,ed,e[i]); 106 } 107 for(int i=1;i<=n;i++) 108 for(int j=i;j<=n;j++) 109 { 110 if(d[i][j]>0) 111 { 112 sum+=d[i][j]; 113 ins(st,id1[i][j],d[i][j]); 114 ins(id1[i][j],cnt+i,999999999); 115 ins(id1[i][j],cnt+j,999999999); 116 } 117 else if(d[i][j]<0) 118 { 119 ins(id1[i][j],ed,-d[i][j]); 120 ins(id1[i][j],cnt+i,999999999); 121 ins(id1[i][j],cnt+j,999999999); 122 } 123 if(i!=j) 124 { 125 ins(id1[i][j],id1[i][j-1],999999999); 126 ins(id1[i][j],id1[i+1][j],999999999); 127 } 128 } 129 return sum; 130 } 131 int main() 132 { 133 qread(n);qread(m); 134 for(int i=1;i<=n;i++)qread(e[i]); 135 for(int i=1;i<=n;i++) 136 for(int j=i;j<=n;j++) 137 qread(d[i][j]); 138 st=0; 139 LL sum=jb(); 140 /* 141 for(int i=1;i<=len;i++) 142 if(a[i].x==0) 143 printf("%d %d\n",a[i].y,a[i].c); 144 printf("\n"); 145 for(int i=1;i<=len;i++) 146 if(a[i].y==ed) 147 printf("%d %d\n",a[i].x,a[i].c); 148 */ 149 int ans=0; 150 while(bfs())ans+=findflow(st,999999999); 151 printf("%lld\n",sum-ans); 152 return 0; 153 }
以上是关于bzoj4873: [Shoi2017]寿司餐厅的主要内容,如果未能解决你的问题,请参考以下文章
最大权闭合子图bzoj4873: [Shoi2017]寿司餐厅