题目背景
班级聚会的时候,班主任为了方便管理,规定吃饭的时候同一个寝室的同学必须坐在一起;但是吃完饭后,到了娱乐时间,喜欢不同游戏的同学会聚到一起;在这个过程中就涉及到了座位分配的问题。
题目描述
有 n 张圆桌排成一排(从左到右依次编号为 0 到 n−1 ),每张桌子有 m 个座位(按照逆时针依次编号为 0到 m−1 ),在吃饭时每个座位上都有一个人;在吃完饭后的时候,每个人都需要选择一个新的座位(新座位可能和原来的座位是同一个),具体来说,第 i 桌第 j 个人的新座位只能在第 Li,j 桌到第 Ri,j 桌中选,可以是这些桌中的任何一个座位。确定好新座位之后,大家开始移动,移动的体力消耗按照如下规则计算:
移动座位过程分为两步:
- 从起始桌移动到目标桌对应座位,这个过程中的体力消耗为两桌距离的两倍,即从第 i 桌移动到第 j 桌对应座位的体力消耗为 2×|i−j|;
2.从目标桌的对应座位绕着桌子移动到目标座位,由于桌子是圆的,所以客人会选择最近的方向移动,体力消耗为移动距离的一倍,即从编号为 x 的座位移动的编号为 y 的座位的体力消耗为 min(|x−y|,m−|x−y|);
详情如下图:
现在,给定每个客人的限制(即每个人的新座位所在的区间),需要你设计一个方案,使得所有客人消耗的体力和最小;本题中假设客人在移动的时候互不影响。
输入格式
从标准输入读入数据。
第一行输入两个数 n 和 m;
接下来输入 n 行,每行 m 个空格隔开的整数描述矩阵 L:其中,第 i 行的第 j 个数表示 Li,j;
接下来输入 n 行,每行 m 个空格隔开的整数描述矩阵 R:其中,第 i 行的第 j 个数表示 Ri,j。
输出格式
输出到标准输出。
输出总体力消耗的最小值,如果没有合法的方案输出no solution
。
-
题解:
- 由原来的人向现在的每个可达的位置连边桌子连边做费用流($zkw$)有70;
- 设源$S$,汇$T$,原来的人为$s_{ij}$,现在的位置为$t_{ij}$,同桌之间移动的代价$c1$,不同桌的为$c2$;
- 这题的一大特点就是原来的人向现在的对应位置的连边是区间$[L_{i,j},R_{i,j}]$;
- 考虑用线段树优化建边,就是所有的$s_{i,j}$点先连向线段树,再连向$t_{i,j}$;
- 由于要共用线段树的节点所以需要对代价$c2$做一些转化;
- 将$t$拆成$t1$和$t2$分别表示不同桌向左走或向右走,$S$连向$s_{i,j}$代价$i*2$ ,$t1$,$t2$连向$T$代价$-i*2$;
- 建两颗线段树,叶子节点分别连向$t1$和$t2$,区间[L,R]拆成[L,i]和[i,R]即可向线段树节点连边;
- 节点个数$O(3*nm + 8*nm)$,边数$O( 3*nm + 4*nm + 8*nm + logn * nm)$
-
1 #include<bits/stdc++.h> 2 #define inf 0x3f3f3f3f 3 using namespace std; 4 const int N=1000010,K=310; 5 int S,T,n,m,o,hd[N],dis[N],vis[N],sum1[K],sum2[K]; 6 int id1[K][K],id2[K][K],id3[K][K],id4[K][K],L[K][K],R[K][K]; 7 struct Edge{int v,nt,f,w;}E[N<<1]; 8 void adde(int u,int v,int f,int w){ 9 E[o]=(Edge){v,hd[u],f,w};hd[u]=o++; 10 E[o]=(Edge){u,hd[v],0,-w};hd[v]=o++; 11 } 12 queue<int>q; 13 bool bfs(){ 14 memset(vis,0,sizeof(vis)); 15 memset(dis,0x3f,sizeof(dis)); 16 q.push(T);dis[T]=0;vis[T]=1; 17 while(!q.empty()){ 18 int u=q.front();q.pop(); 19 vis[u]=0; 20 for(int i=hd[u];~i;i=E[i].nt)if(E[i^1].f){ 21 int v=E[i].v; 22 if(dis[v]>dis[u]+E[i^1].w){ 23 dis[v]=dis[u]+E[i^1].w; 24 if(!vis[v])vis[v]=1,q.push(v); 25 } 26 } 27 } 28 return dis[S]!=inf; 29 } 30 int dfs(int u,int F){ 31 vis[u]=1; 32 if(u==T||!F)return F; 33 int flow=0,f; 34 for(int i=hd[u];~i;i=E[i].nt){ 35 int v=E[i].v; 36 if(!vis[v]&&dis[v]+E[i].w==dis[u]&&E[i].f&&(f=dfs(v,min(F,E[i].f)))){ 37 flow+=f;F-=f; 38 E[i].f-=f,E[i^1].f+=f; 39 if(!F)break; 40 } 41 } 42 return flow; 43 } 44 int zkw(){ 45 int flow=0,cost=0,f; 46 while(bfs()){ 47 do{ 48 memset(vis,0,sizeof(vis)); 49 f=dfs(S,inf); 50 flow+=f; 51 cost+=dis[S]*f; 52 }while(vis[T]); 53 } 54 return flow==n*m?cost:-1; 55 } 56 int main(){ 57 // freopen("C.in","r",stdin); 58 // freopen("C.out","w",stdout); 59 memset(hd,-1,sizeof(hd)); 60 scanf("%d%d",&n,&m); 61 for(int i=1;i<=n;i++) 62 for(int j=1;j<=m;j++){ 63 id1[i][j]=(i-1)*m+j; 64 id2[i][j]=n*m+id1[i][j]; 65 id3[i][j]=n*m+id2[i][j]; 66 id4[i][j]=n*m+id3[i][j]; 67 } 68 S=0,T=id4[n][m]+1; 69 for(int i=1;i<=n;i++){ 70 for(int j=1;j<=m;j++){ 71 adde(S,id1[i][j],1,0); 72 adde(id2[i][j],id4[i][j],1,0); 73 adde(id3[i][j],id4[i][j],1,0); 74 adde(id4[i][j],T,1,0); 75 int ri=j%m+1,le=(j+m-2)%m+1; 76 adde(id2[i][j],id2[i][ri],inf,1); 77 adde(id2[i][j],id2[i][le],inf,1); 78 adde(id3[i][j],id3[i][ri],inf,1); 79 adde(id3[i][j],id3[i][le],inf,1); 80 if(i>1)adde(id2[i][j],id2[i-1][j],inf,2); 81 if(i<n)adde(id3[i][j],id3[i+1][j],inf,2); 82 } 83 } 84 for(int i=1;i<=n;i++) 85 for(int j=1;j<=m;j++){scanf("%d",&L[i][j]);sum2[++L[i][j]]++;} 86 for(int i=1;i<=n;i++) 87 for(int j=1;j<=m;j++){scanf("%d",&R[i][j]);sum1[++R[i][j]]++;} 88 for(int i=1;i<=n;i++){ 89 sum1[i]+=sum1[i-1]; 90 if(sum1[i]>i*m)return puts("no solution"),0; 91 } 92 for(int i=n;i>=1;i--){ 93 sum2[i]+=sum2[i+1]; 94 if(sum2[i]>(n-i+1)*m)return puts("no solution"),0; 95 } 96 for(int i=1;i<=n;i++) 97 for(int j=1;j<=m;j++){ 98 if(L[i][j]<=i&&i<=R[i][j])adde(id1[i][j],id2[i][j],1,0),adde(id1[i][j],id3[i][j],1,0); 99 else if(i<L[i][j])adde(id1[i][j],id3[L[i][j]][j],1,(L[i][j]-i)<<1); 100 else adde(id1[i][j],id2[R[i][j]][j],1,(i-R[i][j])<<1); 101 } 102 int ans = zkw(); 103 if(!~ans)puts("-1"); 104 else printf("%d ",ans); 105 return 0; 106 }
-
1 #include<bits/stdc++.h> 2 #define inf 0x3f3f3f3f 3 #define il inline 4 #define ID(i,j) (i-1)*m+j 5 using namespace std; 6 const int N=100010,M=100010; 7 int n,m,L[301][11],R[301][11],ls1[1801],rs1[1801],ls2[1801],rs2[1801],cnt,rt1,rt2; 8 int S,T,o,hd[N],vis[N],dis[N],id1[301],id2[301],q[N],head,tail; 9 struct Edge{int v,nt,f,w;}E[M<<1]; 10 il void adde(int u,int v,int f,int w){ 11 // printf("%d %d %d %d ",u,v,f,w); 12 E[o]=(Edge){v,hd[u],f,w};hd[u]=o++; 13 E[o]=(Edge){u,hd[v],0,-w};hd[v]=o++; 14 } 15 il void Adde(int u,int v,int f,int w){ 16 for(int i=1;i<=m;i++)adde(ID(u,i),ID(v,i),f,w); 17 } 18 void build1(int&k,int l,int r){ 19 k=++cnt; 20 if(l==r){Adde(k,id2[l],inf,-2*l);return;} 21 int mid=(l+r)>>1; 22 build1(ls1[k],l,mid); 23 build1(rs1[k],mid+1,r); 24 Adde(k,ls1[k],inf,0); 25 Adde(k,rs1[k],inf,0); 26 } 27 void build2(int&k,int l,int r){ 28 k=++cnt; 29 if(l==r){Adde(k,id2[l],inf,-2*(n-l+1));return;} 30 int mid=(l+r)>>1; 31 build2(ls2[k],l,mid); 32 build2(rs2[k],mid+1,r); 33 Adde(k,ls2[k],inf,0); 34 Adde(k,rs2[k],inf,0); 35 } 36 void update1(int k,int l,int r,int x,int y,int i,int j,int val){ 37 if(l==x&&r==y){adde(ID(id1[i],j),ID(k,j),inf,val);} 38 else{ 39 int mid=(l+r)>>1; 40 if(y<=mid)update1(ls1[k],l,mid,x,y,i,j,val); 41 else if(x>mid)update1(rs1[k],mid+1,r,x,y,i,j,val); 42 else update1(ls1[k],l,mid,x,mid,i,j,val),update1(rs1[k],mid+1,r,mid+1,y,i,j,val); 43 } 44 } 45 void update2(int k,int l,int r,int x,int y,int i,int j,int val){ 46 if(l==x&&r==y){adde(ID(id1[i],j),ID(k,j),inf,val);} 47 else{ 48 int mid=(l+r)>>1; 49 if(y<=mid)update2(ls2[k],l,mid,x,y,i,j,val); 50 else if(x>mid)update2(rs2[k],mid+1,r,x,y,i,j,val); 51 else update2(ls2[k],l,mid,x,mid,i,j,val),update2(rs2[k],mid+1,r,mid+1,y,i,j,val); 52 } 53 } 54 bool spfa(){ 55 for(int i=0;i<=cnt*m;i++)vis[i]=0,dis[i]=inf; 56 head=tail=0;dis[q[tail++]=T]=0; 57 while(head!=tail){ 58 int u=q[head++];if(head==N)head=0; 59 vis[u]=0; 60 for(int i=hd[u];~i;i=E[i].nt)if(E[i^1].f){ 61 int v=E[i].v; 62 if(dis[v]>dis[u]+E[i^1].w){ 63 dis[v]=dis[u]+E[i^1].w; 64 if(!vis[v]){ 65 vis[v]=1,q[tail++]=v; 66 if(tail==N)tail=0; 67 } 68 } 69 } 70 } 71 return dis[S]!=inf; 72 } 73 int dfs(int u,int F){ 74 vis[u]=1; 75 if(u==T||!F)return F; 76 int flow=0,f; 77 for(int i=hd[u];~i;i=E[i].nt){ 78 int v=E[i].v; 79 if(E[i].f&&!vis[v]&&dis[v]+E[i].w==dis[u]&&(f=dfs(v,min(F,E[i].f)))){ 80 flow+=f,F-=f; 81 E[i].f-=f,E[i^1].f+=f; 82 if(!F)break; 83 } 84 } 85 return flow; 86 } 87 int zkw(){ 88 int flow=0,cost=0,f; 89 while(spfa()){ 90 do{ 91 for(int i=0;i<=cnt*m;i++)vis[i]=0; 92 f=dfs(S,inf); 93 flow+=f; 94 cost+=dis[S]*f; 95 }while(vis[T]); 96 } 97 return (flow==n*m)?cost:-1; 98 } 99 int main(){ 100 freopen("C.in","r",stdin); 101 freopen("C.out","w",stdout); 102 memset(hd,-1,sizeof(hd)); 103 scanf("%d%d",&n,&m); 104 for(int i=1;i<=n;i++) 105 for(int j=1;j<=m;j++) 106 scanf("%d",&L[i][j]),L[i][j]++; 107 for(int i=1;i<=n;i++) 108 for(int j=1;j<=m;j++) 109 scanf("%d",&R[i][j]),R[i][j]++; 110 S=0;T=++cnt; 111 for(int i=1;i<=n;i++){ 112 id1[i]=++cnt; 113 id2[i]=++cnt; 114 } 115 build1(rt1,1,n); 116 build2(rt2,1,n); 117 for(int i=1;i<=n;i++) 118 for(int j=1;j<=m;j++){ 119 adde(S,ID(id1[i],j),1,0); 120 adde(ID(id2[i],j),T,1,0); 121 adde(ID(id2[i],j),ID(id2[i],j%m+1),inf,1); 122 adde(ID(id2[i],j),ID(id2[i],(j+m-2)%m+1),inf,1); 123 if(R[i][j]<=i)update1(rt1,1,n,L[i][j],R[i][j],i,j,2*i); 124 else if(L[i][j]>=i)update2(rt2,1,n,L[i][j],R[i][j],i,j,2*(n-i+1)); 125 else update1(rt1,1,n,L[i][j],i,i,j,2*i), 126 update2(rt2,1,n,i,R[i][j],i,j,2*(n-i+1)); 127 } 128 int ans=zkw(); 129 if(!~ans)puts("no solution"); 130 else printf("%d ",ans); 131 return 0; 132 }