woj4782~4784
剪刀运送
咕。
走路
送分题
送xx分,,
100个点,100个颜色,每个点每次可以选择成为自己或周围任何一个出点的颜色。求一种2n^2以内的,从起始状态到终结状态的方案。
这是道前置结论题。
首先研究无解的情况。
如果我们保证有合法数量的方案,那还有无解的,只能是终结状态的某种颜色,起始状态没有。
接下来考虑怎么转变状态。
拆分问题,从每个点到对应颜色,变成每种颜色的数量先相等。
所以我们的操作1本质是:修改一个点的颜色。
我们胡乱地把颜色统一。修改方式只能是将一种少了的颜色,通过某种给多了的颜色。这样少的可以变多,多的可以变少。其它情况都没意义。
那怎么传递呢。抽象出一条链。我们要把起点的颜色修改为终点的颜色。而路上为了保证别的颜色数量不变,只能是交换。
也就是说,我变成你,你变成我,颜色交换,传递过去。只有在起点的时候,直接赋值。
每次交换都是一次状态变化,我们要答案++。记录下来。
现在颜色数量一样了,但点色不对应。
我们开始处理,如果发生不对应,我们就要找一个这样的颜色,然后把它传过来。
传的过程中,保证不影响已经弄好的颜色。
所以第二个操作是:在给定范围内,交换颜色。这是第一个操作的弱化版。
因为颜色数量是一样的,所以最后一定能弄到一起。这样我们就做完了。
哦对了,图不一定联通,所以要都扫一遍,用一种数据结构把联通块内点记录下来。
差不多了。
#include<bits/stdc++.h>
using namespace std;
#define in read()
int in{
int cnt=0,f=1;char ch=0;
while(!isdigit(ch)){
ch=getchar();if(ch=='-')f=-1;
}
while(isdigit(ch)){
cnt=cnt*10+ch-48;
ch=getchar();
}return cnt*f;
}
const int N=103;
int c1[N],c2[N],a[N],b[N],ans[30003][N],g[N][N],n,m,k;
int cnt;int vis[N];int cntq;int v[N];int belong[N];
int q[N];
void dfs1(int u){
//cout<<u<<" ";
q[++cntq]=u;vis[u]=1;
c1[a[u]]++;c2[b[u]]++;
for(int i=1;i<=n;i++){
if(i==u)continue;
if(vis[i]||!g[u][i])continue;
dfs1(i);
}
}
int dfs2(int now,int T,int fa){
if(now==T)return 1;v[now]=1;
for(int i=1;i<=n;i++){
if(i==now)continue;
if(g[now][i]&&!v[i]&&dfs2(i,T,now)){
cnt++;memcpy(ans[cnt],ans[cnt-1],sizeof(ans[cnt-1]));
if(fa==-1)ans[cnt][now]=ans[cnt][i];else swap(ans[cnt][now],ans[cnt][i]);
return 1;
}
}return 0;
}
int dfs3(int now,int T,int limit){
if(now==T)return 1;v[now]=1;
for(int i=1;i<=n;i++){
if(i==now)continue;
if(g[now][i]&&!v[i]&&belong[i]<=limit&&dfs3(i,T,limit)){
++cnt;memcpy(ans[cnt],ans[cnt-1],sizeof(ans[cnt-1]));
swap(ans[cnt][now],ans[cnt][i]);return 1;
}
}return 0;
}
signed main(){
n=in;m=in;k=in;
for(int i=1;i<=n;i++)a[i]=in;for(int i=1;i<=n;i++)b[i]=in;
for(int i=1;i<=m;i++){int x=in;int y=in;g[x][y]=g[y][x]=1;}
++cnt;memcpy(ans[cnt],a,sizeof(a));
// for(int i=1;i<=n;i++)cout<<g[4][i]<<" ";cout<<endl;
for(int i=1;i<=n;i++){
if(vis[i])continue;//cout<<"###################"<<endl;
//cout<<cnt<<" ";for(int ii=1;ii<=n;ii++)cout<<ans[cnt][ii]<<" ";cout<<endl;
memset(c1,0,sizeof(c1));memset(c2,0,sizeof(c2));
vis[i]=1;cntq=0;dfs1(i);//cout<<endl;
//for(int ii=0;ii<k;ii++)cout<<c1[ii]<<" ";cout<<endl;for(int ii=0;ii<k;ii++)cout<<c2[ii]<<" ";cout<<endl;
for(int j=0;j<k;j++)if(c2[j]&&!c1[j]){
cout<<"Impossible";return 0;
}
while(1){
int flag=0;
for(int j=1;j<=cntq;j++){
if(c1[ans[cnt][q[j]]]>c2[ans[cnt][q[j]]]){
flag=1;
for(int l=1;l<=cntq;l++){
if(c1[ans[cnt][q[l]]]<c2[ans[cnt][q[l]]]){
c1[ans[cnt][q[l]]]++;c1[ans[cnt][q[j]]]--;
memset(v,0,sizeof(v));
dfs2(q[j],q[l],-1);break;
}
}
break;
}
}
if(!flag)break;
}
for(int j=1;j<=cntq;j++){belong[q[j]]=j;}
for(int j=cntq;j>=1;j--){
if(ans[cnt][q[j]]!=b[q[j]]){
for(int l=1;l<j;l++){
if(ans[cnt][q[l]]==b[q[j]]){
memset(v,0,sizeof(v));
dfs3(q[j],q[l],j);break;
}
}
}
}
}
for(int i=1;i<=cnt;i++){
for(int j=1;j<=n;j++)cout<<ans[i][j]<<" ";cout<<endl;
}
return 0;
}