题解:
将所有点拆开。
$0$点的拆点之间费用为$0$;
$2$点的拆点之间费用为$-1$。
所有点不能到$1$上。
然后最大费用流。
代码:
#include<queue> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define N 3250 const int inf = 0x3f3f3f3f; inline int rd() { int f=1,c=0;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){c=10*c+ch-'0';ch=getchar();} return f*c; } int n,p,q,hed[N],cnt=-1,S,T; int mp[40][40]; int _id(int x,int y) { return (x-1)*p+y; } int get_y(int u) { int ret = u%p; if(!ret)ret+=p; return ret; } struct EG { int to,nxt,w,c; }e[N*200]; void ae(int f,int t,int w,int c) { e[++cnt].to = t; e[cnt].nxt = hed[f]; e[cnt].w = w; e[cnt].c = c; hed[f] = cnt; } int dep[N],fl[N]; int pre[N],fa[N]; bool vis[N]; queue<int>que; bool spfa() { memset(dep,0x3f,sizeof(dep)); dep[S]=0,fl[S]=inf,vis[S]=1;que.push(S); while(!que.empty()) { int u = que.front(); que.pop(); for(int j=hed[u];~j;j=e[j].nxt) { int to = e[j].to; if(e[j].w&&dep[to]>dep[u]+e[j].c) { dep[to] = dep[u]+e[j].c; fl[to] = min(fl[u],e[j].w); pre[to] = j,fa[to] = u; if(!vis[to]) { vis[to] = 1; que.push(to); } } } vis[u] = 0; } return dep[T]!=inf; } int sta[N],tl; void mcmf() { while(spfa()) { int u = T; while(u!=S) { e[pre[u]].w-=fl[T]; e[pre[u]^1].w+=fl[T]; u = fa[u]; } } } void dfs(int u,int c) { for(int j=hed[u];~j;j=e[j].nxt) { int to = e[j].to; if(to==S||to==T)continue; if((to>>1)<=(u>>1))continue; if(e[j].w==inf)continue; e[j].w++; printf("%d %d\n",c,get_y(to>>1)!=get_y(u>>1)); dfs(to+1,c); return ; } } void print() { for(int i=1;i<=n;i++) dfs(3,i); } int main() { n = rd(),p = rd(),q = rd(); S = 0,T = 1; memset(hed,-1,sizeof(hed)); for(int i=1;i<=q;i++) for(int j=1;j<=p;j++) mp[i][j]=rd(); ae(S,2,n,0),ae(2,S,0,0); ae(p*q*2+1,T,n,0),ae(T,p*q*2+1,0,0); for(int i=1;i<=q;i++) for(int j=1;j<=p;j++) { if(mp[i][j]==1)continue; int u = _id(i,j); if(i!=q) { if(mp[i+1][j]!=1) { int to = _id(i+1,j); ae(u<<1|1,to<<1,inf,0); ae(to<<1,u<<1|1,0,0); } } if(j!=p) { if(mp[i][j+1]!=1) { int to = _id(i,j+1); ae(u<<1|1,to<<1,inf,0); ae(to<<1,u<<1|1,0,0); } } if(mp[i][j]==2) { ae(u<<1,u<<1|1,1,-1); ae(u<<1|1,u<<1,0,1); } ae(u<<1,u<<1|1,inf,0); ae(u<<1|1,u<<1,0,0); } mcmf(); print(); return 0; }