[TJOI2013]循环格
生活随笔
收集整理的這篇文章主要介紹了
[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]循环格的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java一行一行的读文件和简单的写文件
- 下一篇: Ubuntu使用——23(dock的美化