当前位置:
首页 >
[luoguP4142]洞穴遇险
发布时间:2023/11/30
50
豆豆
生活随笔
收集整理的这篇文章主要介绍了
[luoguP4142]洞穴遇险
小编觉得挺不错的,现在分享给大家,帮大家做个参考.
https://www.zybuluo.com/ysner/note/1240792
题面
戳我
解析
这种用来拼接的奇形怪状的东西,要不就是轮廓线\(DP\),要不就是网络流。
为了表示奇数点(即\((x+y)\%2=1\))的危险值,把该点拆为两个点,连一条边长为该点危险值相反数的边(两点分别称为起点和终点)。
鉴于一根柱子跨越\(3\)个格子,其中一点为奇数点,另外两个点都是偶数点,不能区分。
于是也要把偶数点分为两类(不用拆点)。一类连源点,一类连汇点。连汇点的一类连奇数点的起点,另一类连终点。(让源点出发能到汇点就成)
然后思考如何表示柱子。
如果强行给柱子规定方向,则有\(8\)个方向。
表示出来,有两种情况,一是\(x\)轴方向出,\(y\)轴方向进;另一种是\(y\)轴方向进,\(x\)轴方向出。
于是两个奇数点分别反映一种情况,同时注意相邻的偶数点连奇数点中的起点、还是终点即可。
还要注意的是,最小费用最大流模板求出的是在最大流前提下的最小流,在后期,可能为了得到最大流而付出更多费用(在本题中就是为了放更多柱子而增加不稳定度)。在费用开始非负时(开始退流时)记得\(break\)。
唯一一种能让网络流TLE的方式就是cnt=0
// luogu-judger-enable-o2 #include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<algorithm> #include<vector> #include<queue> #define re register #define il inline #define ll long long #define max(a,b) ((a)>(b)?(a):(b)) #define min(a,b) ((a)<(b)?(a):(b)) #define fp(i,a,b) for(re int i=a;i<=b;i++) #define fq(i,a,b) for(re int i=a;i>=b;i--) using namespace std; const int mod=1e9+7,N=5e3+100; struct Edge{int to,nxt,w,c;}e[N*10]; int n,m,k,s,sum,h[N],d[55][55],ans=0,dis[N],S,T,pe[N],pv[N],tot,cnt=1,g; bool vis[N],ban[55][55]; il void add(re int u,re int v,re int w,re int c) {if(u==-1||v==-1) return ;e[++cnt]=(Edge){v,h[u],w,c};h[u]=cnt;e[++cnt]=(Edge){u,h[v],0,-c};h[v]=cnt; } queue<int>Q; il ll gi() {re ll x=0,t=1;re char ch=getchar();while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();if(ch=='-') t=-1,ch=getchar();while(ch>='0'&&ch<='9') x=x*10+ch-48,ch=getchar();return x*t; } il int id(re int x,re int y){return (x-1)*n+y;} il int SPFA() {memset(dis,63,sizeof(dis));dis[S]=0;vis[S]=1;Q.push(S);while(!Q.empty()){re int u=Q.front();Q.pop();for(re int i=h[u];i+1;i=e[i].nxt){re int v=e[i].to;//printf("!!!%d %d\n",u,v);if(dis[v]>dis[u]+e[i].c&&e[i].w){dis[v]=dis[u]+e[i].c;pe[v]=i;pv[v]=u;if(!vis[v]) vis[v]=1,Q.push(v);}}vis[u]=0;}return dis[T]<dis[0]; } int main() {//freopen("marshland.in","r",stdin);//freopen("marshland.out","w",stdout);memset(h,-1,sizeof(h));n=gi();m=gi();k=gi();g=n*n;S=2*g+1;T=2*g+2;fp(i,1,n)fp(j,1,n)d[i][j]=gi(),s+=d[i][j];fp(i,1,k){re int u=gi(),v=gi();ban[u][v]=1;}fp(i,1,n)fp(j,1,n){if(ban[i][j]) continue;if((i+j)%2) add(id(i,j),id(i,j)+g,1,-d[i][j]);if((i+j)%2&&j%2==0){if(i>1&&!ban[i-1][j]) add(id(i,j)+g,id(i-1,j),1,0);if(i<n&&!ban[i+1][j]) add(id(i,j)+g,id(i+1,j),1,0);if(j>1&&!ban[i][j-1]) add(id(i,j-1),id(i,j),1,0);if(j<n&&!ban[i][j+1]) add(id(i,j+1),id(i,j),1,0);}if((i+j)%2&&j%2==1){if(i>1&&!ban[i-1][j]) add(id(i-1,j),id(i,j),1,0);if(i<n&&!ban[i+1][j]) add(id(i+1,j),id(i,j),1,0);if(j>1&&!ban[i][j-1]) add(id(i,j)+g,id(i,j-1),1,0);if(j<n&&!ban[i][j+1]) add(id(i,j)+g,id(i,j+1),1,0);}if((i+j)%2==0&&j%2==1) add(S,id(i,j),1,0);if((i+j)%2==0&&j%2==0) add(id(i,j),T,1,0);}while(SPFA()&&m){if(dis[T]>=0) break;sum=2e9;for(re int i=T;i!=S;i=pv[i])sum=min(sum,e[pe[i]].w);m-=sum;//printf("%d\n",sum);for(re int i=T;i!=S;i=pv[i])e[pe[i]].w-=sum,e[pe[i]^1].w+=sum,ans+=sum*e[pe[i]].c;}printf("%d\n",s+ans);fclose(stdin);fclose(stdout);return 0; }转载于:https://www.cnblogs.com/yanshannan/p/9433035.html
创作挑战赛新人创作奖励来咯,坚持创作打卡瓜分现金大奖总结
以上是生活随笔为你收集整理的[luoguP4142]洞穴遇险的全部内容,希望文章能够帮你解决所遇到的问题。
- 上一篇: asp.net core Serilog
- 下一篇: css3 变换、过渡效果、动画