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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

[TJOI2013]循环格

發布時間:2025/7/14 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [TJOI2013]循环格 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題目

我也不知道我建了個什么圖,之后隨便跑了跑就過了

發現要求形成一個環,改邊的方向需要\(1\)的代價

根據網絡流的套路開始拆點

  • 每個點拆成兩個點,\(S\)向入點連流量為\(1\)的邊,出點向\(T\)連流量為\(1\)的邊

  • 對于那些方向改變的邊,費用都是\(1\),否則是\(0\)

  • 這樣為什么是對的呢,考慮一下如果形成了一個環,那么每一點的流量都會在下一個點被排掉,顯然之后環才能保證所有的點的流量都被排掉

    當然這道題的主流做法是利用每一個點的入度出度僅為\(1\)的性質,發揮網絡流調整的特性來做的

    其實本質是一樣的因為圖建出來是一樣的

    #include<queue> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define re register #define LL long long #define max(a,b) ((a)>(b)?(a):(b)) #define min(a,b) ((a)<(b)?(a):(b)) const int maxn=505; const int inf=999999999; inline int read() {char c=getchar();int x=0;while(c<'0'||c>'9') c=getchar();while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-48,c=getchar();return x; } int n,m,S,T,num=1; std::queue<int> q; struct E{int v,nxt,w,f;}e[maxn*maxn]; int head[maxn],vis[maxn],d[maxn]; inline void C(int x,int y,int w,int f) {e[++num].v=y;e[num].nxt=head[x];head[x]=num;e[num].f=f;e[num].w=w; } inline void add(int x,int y,int w,int f) {C(x,y,w,f),C(y,x,-1*w,0);} char map[20][20]; int in[20][20],out[20][20]; const int dx[]={0,0,-1,1}; const int dy[]={-1,1,0,0}; inline int SPFA() {for(re int i=S;i<=T;i++) d[i]=inf,vis[i]=0;d[T]=0,q.push(T);while(!q.empty()) {int k=q.front();q.pop();vis[k]=0;for(re int i=head[k];i;i=e[i].nxt)if(e[i^1].f&&d[e[i].v]>d[k]+e[i^1].w) {d[e[i].v]=d[k]+e[i^1].w;if(!vis[e[i].v]) q.push(e[i].v),vis[e[i].v]=0;}}return d[S]<inf; } int dfs(int x,int now) {if(x==T||!now) return now;vis[x]=1;int flow=0,ff;for(re int i=head[x];i;i=e[i].nxt)if(!vis[e[i].v]&&e[i].f&&d[e[i].v]==d[x]+e[i^1].w){ff=dfs(e[i].v,min(e[i].f,now));if(ff<=0) continue;now-=ff,flow+=ff,e[i].f-=ff,e[i^1].f+=ff;if(!now) break;}return flow; } inline int check(char A) {if(A=='L') return 0;if(A=='R') return 1;if(A=='U') return 2;return 3; } int main() {n=read(),m=read();for(re int i=1;i<=n;i++) scanf("%s",map[i]+1);for(re int i=1;i<=n;i++)for(re int j=1;j<=m;j++) in[i][j]=++T;for(re int i=1;i<=n;i++)for(re int j=1;j<=m;j++) out[i][j]=++T;++T;for(re int i=1;i<=n;i++)for(re int j=1;j<=m;j++) add(S,in[i][j],0,1),add(out[i][j],T,0,1);for(re int i=1;i<=n;i++)for(re int j=1;j<=m;j++) map[i][j]=check(map[i][j]);for(re int i=1;i<=n;i++)for(re int j=1;j<=m;j++) for(re int k=0;k<4;k++) {int x=i+dx[k],y=j+dy[k];if(x<1) x=n;if(y<1) y=m;if(x>n) x=1;if(y>m) y=1;add(in[i][j],out[x][y],k!=map[i][j],1);}int ans=0;while(SPFA()) {vis[T]=1;while(vis[T]) {for(re int i=S;i<=T;i++) vis[i]=0;ans+=dfs(S,inf)*d[S];}}printf("%d",ans);return 0; }

    轉載于:https://www.cnblogs.com/asuldb/p/10554818.html

    總結

    以上是生活随笔為你收集整理的[TJOI2013]循环格的全部內容,希望文章能夠幫你解決所遇到的問題。

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