日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

YbtOJ#593-木棍问题【费用流】

發布時間:2023/12/3 编程问答 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 YbtOJ#593-木棍问题【费用流】 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

正題

題目鏈接:https://www.ybtoj.com.cn/contest/114/problem/3


題目大意

n?mn*mn?m的網格上有一些格子有木球,兩個相鄰木球直接可以有木棍。
兩個LLL形的木棍會產生AAA的代價,兩個III形的木棍會產生BBB的代價

對于每個kkk求出插入kkk根木棍時的最小代價。

n,m∈[1,40],1≤A≤B≤105n,m\in[1,40],1\leq A\leq B\leq 10^5n,m[1,40],1AB105


解題思路

因為B≥AB\geq ABA可以理解為兩個相鄰的木棍會產生AAA點代價,III形的會額外產生B?AB-AB?A點代價。

先不考慮B?AB-AB?A的部分,考慮每個點的貢獻,一個點的度數為iii時會產生(i2)\binom{i}{2}(2i?)的貢獻,并且相鄰的點之間可以連邊。這是一個很經典的費用流模型。

對網格黑白染色,黑色的源點連接,白色的連接匯點。對于每個連接可以分為444條邊,流量都為111,權值分別為(12)?(02),(22)?(12),(32)?(22),(42)?(32)\binom12-\binom02\ ,\ \binom22-\binom12\ ,\ \binom32-\binom22\ ,\ \binom42-\binom32(21?)?(20?)?,?(22?)?(21?)?,?(23?)?(22?)?,?(24?)?(23?)

這些權值遞增,費用流優先流小的,所以如果流量為iii那個剛好費用和就是(i2)\binom i2(2i?)。

然后考慮III形的額外代價,其實就是如果一個點的橫縱向度數到222就會產生代價。我們可以故技重施,對于每個點再開兩個點分別表示橫向/縱向,連接這些點的時候一條邊權值是000,另一條是B?AB-AB?A

然后正常EkEkEk費用流跑法會每次擴展一個流量,每次輸出就好了。


code

#include<cstdio> #include<cstring> #include<algorithm> #include<queue> using namespace std; const int N=5100,inf=2147483647/3; const int dx[4]={1,-1,0,0},dy[4]={0,0,1,-1}; struct node{int to,next,w,c; }a[N<<5]; int op,n,m,A,B,s,t,cnt,tot=1,ans; int f[N],mf[N],ls[N],pre[N],p[50][50]; char c[50][50];bool v[N]; queue<int>q; void addl(int x,int y,int w,int c){a[++tot].to=y;a[tot].next=ls[x];ls[x]=tot;a[tot].w=w;a[tot].c=c;a[++tot].to=x;a[tot].next=ls[y];ls[y]=tot;a[tot].w=0;a[tot].c=-c;return; } bool SPFA(){memset(f,0x3f,sizeof(f));q.push(s);f[s]=0;v[s]=1;mf[s]=inf;while(!q.empty()){int x=q.front();v[x]=0;q.pop();for(int i=ls[x];i;i=a[i].next){int y=a[i].to;if(!a[i].w)continue;if(f[x]+a[i].c<f[y]){f[y]=f[x]+a[i].c;pre[y]=i;mf[y]=min(mf[x],a[i].w);if(!v[y])q.push(y),v[y]=1;}}}return f[t]<inf; } void Updata(){int x=t;ans+=f[t];if(op)printf("%d\n",(ans!=0));else printf("%d\n",ans);while(x!=s){a[pre[x]].w-=mf[t];a[pre[x]^1].w+=mf[t];x=a[pre[x]^1].to;}return; } int main() {freopen("trouble.in","r",stdin);freopen("trouble.out","w",stdout);scanf("%d",&op);op=((op>=8)&&(op<=12));scanf("%d%d%d%d",&n,&m,&A,&B);B-=A;for(int i=1;i<=n;i++){scanf("%s",c[i]+1);for(int j=1;j<=m;j++)if(c[i][j]=='0')p[i][j]=++cnt;}s=3*cnt+1;t=s+1;for(int i=1;i<=n;i++)for(int j=1;j<=m;j++){if(c[i][j]=='0'){int x=p[i][j];if((i+j)&1){addl(s,x*3-2,1,0); addl(s,x*3-2,1,A);addl(s,x*3-2,1,2*A); addl(s,x*3-2,1,3*A);addl(x*3-2,x*3-1,1,0);addl(x*3-2,x*3,1,0);addl(x*3-2,x*3-1,1,B);addl(x*3-2,x*3,1,B);for(int k=0;k<4;k++){int zx=i+dx[k],zy=j+dy[k];if(c[zx][zy]!='0')continue;int y=p[zx][zy];if(k<2)addl(x*3-1,y*3-1,1,0);else addl(x*3,y*3,1,0);}}else{addl(x*3-2,t,1,0); addl(x*3-2,t,1,A);addl(x*3-2,t,1,2*A); addl(x*3-2,t,1,3*A);addl(x*3-1,x*3-2,1,0);addl(x*3,x*3-2,1,0);addl(x*3-1,x*3-2,1,B);addl(x*3,x*3-2,1,B);}}}while(SPFA())Updata();return 0; }

總結

以上是生活随笔為你收集整理的YbtOJ#593-木棍问题【费用流】的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。