bzoj3171: [Tjoi2013]循环格(费用流)
其实这题的建图并不难(虽然我并没有想出来)
首先,每一个点的入度和出度必须为$1$
那么我们考虑拆点
每个点的出度点向它能到达的点的入度点连边,容量$1$,如果方向为原来的方向则费用$0$否则费用$1$
然后源点向所有入度点连边,所有出度点向汇点连边
因为费用流首先是最大流,所以肯定能跑满
那么最小费用就是答案了
1 //minamoto 2 #include<iostream> 3 #include<cstdio> 4 #include<cstring> 5 #include<queue> 6 #define inf 0x3f3f3f3f 7 using namespace std; 8 const int N=505,M=100005; 9 int head[N],Next[M],ver[M],edge[M],cost[M],tot=1; 10 inline void add(int u,int v,int e,int c){ 11 ver[++tot]=v,Next[tot]=head[u],head[u]=tot,edge[tot]=e,cost[tot]=c; 12 ver[++tot]=u,Next[tot]=head[v],head[v]=tot,edge[tot]=0,cost[tot]=-c; 13 } 14 int dis[N],vis[N],cur[N],S,T,ans; 15 queue<int> q; 16 bool spfa(){ 17 memset(dis,-1,sizeof(dis)); 18 memset(vis,0,sizeof(vis)); 19 memcpy(cur,head,sizeof(int)*(T-S+1)); 20 q.push(T),dis[T]=0,vis[T]=1; 21 while(!q.empty()){ 22 int u=q.front();q.pop();vis[u]=0; 23 for(int i=head[u];i;i=Next[i]) 24 if(edge[i^1]){ 25 int v=ver[i],c=cost[i]; 26 if(dis[v]<0||dis[v]>dis[u]-c){ 27 dis[v]=dis[u]-c; 28 if(!vis[v]) vis[v]=1,q.push(v); 29 } 30 } 31 } 32 return ~dis[S]; 33 } 34 int dfs(int u,int limit){ 35 if(u==T||!limit) return limit; 36 int flow=0,f;vis[u]=1; 37 for(int i=cur[u];i;cur[u]=i=Next[i]){ 38 int v=ver[i]; 39 if(dis[v]==dis[u]-cost[i]&&!vis[v]&&(f=dfs(v,min(limit,edge[i])))){ 40 flow+=f,limit-=f; 41 edge[i]-=f,edge[i^1]+=f; 42 ans+=f*cost[i]; 43 if(!limit) break; 44 } 45 } 46 vis[u]=0; 47 return flow; 48 } 49 void zkw(){ 50 while(spfa()) dfs(S,inf); 51 } 52 int id[N][N],c[N],n,m;char s[N]; 53 int dx[]={0,0,-1,1},dy[]={-1,1,0,0}; 54 int main(){ 55 //freopen("testdata.in","r",stdin); 56 c['L']=0,c['R']=1,c['U']=2,c['D']=3; 57 scanf("%d%d",&n,&m); 58 S=0,T=n*m*2+1; 59 for(int i=1;i<=n;++i) 60 for(int j=1;j<=m;++j) 61 id[i][j]=(i-1)*m+j; 62 for(int i=1;i<=n;++i){ 63 scanf("%s",s+1); 64 for(int j=1;j<=m;++j) 65 for(int k=0;k<4;++k){ 66 int x=(i+dx[k]-1+n)%n+1,y=(j+dy[k]-1+m)%m+1; 67 (k==c[s[j]])?add(id[i][j],id[x][y]+n*m,1,0):add(id[i][j],id[x][y]+n*m,1,1); 68 } 69 } 70 for(int i=1;i<=n*m;++i) 71 add(S,i,1,0),add(i+n*m,T,1,0); 72 zkw(); 73 printf("%d\n",ans); 74 return 0; 75 }
深深地明白自己的弱小