你说得对,但是我在 P4003 无限之环 获得了 2pts 的高分,你也来试试吧!
#include<bits/stdc++.h>
using namespace std;
const int N=2005,K=10050,INF=1e9;
int n,m;
int arr[N][N],varr[N][N],ans;
struct Node {int v,w,c,id;};
vector<Node> vec[K];
int S,T;
void add(int u,int v,int w,int c) {
vec[u].push_back({v,w,c,vec[v].size()});
vec[v].push_back({u,0,-c,vec[u].size()-1});
}
// 网络流部分
int dis[K],cur[K];
bool vis[K];
queue<int> que;
bool SPFA() {
memset(dis,63,sizeof(dis));
memset(cur,0,sizeof(cur));
dis[S]=0;que.push(S);
int u;
while(!que.empty()) {
u=que.front();
que.pop();vis[u]=0;
for(auto& [v,w,c,id]:vec[u]) {
if(!w || dis[v]<=dis[u]+c) continue;
dis[v]=dis[u]+c;
if(!vis[v]) vis[v]=1,que.push(v);
}
}
return dis[T]<INF;
}
int dfs(int u,int flow) {
if(u==T) return flow;
vis[u]=1;
int v,c,w,cnt=0,d;
for(int i=cur[u];i<vec[u].size();++i) {
cur[u]=i;
v=vec[u][i].v,w=vec[u][i].w,c=vec[u][i].c;
if(!vis[v] && dis[v]==dis[u]+c && w) {
d=dfs(v,min(w,flow-cnt));
vec[v][vec[u][i].id].w+=d;
vec[u][i].w-=d;
cnt+=d,ans+=d*c;
if(cnt==flow) {vis[u]=0;return cnt;}
}
}
vis[u]=0;
return cnt;
}
int rorate_l(int num) {
num=num<<1;
if(num>15) num-=15;
return num;
}
int rorate_r(int num) {
if(num&1) num+=15;
num=num>>1;
return num;
}
int main() {
cin >> n >> m;
for(int i=1;i<=n;++i) {
for(int j=1;j<=m;++j) {
cin >> arr[i][j];
}
}
int id;S=5*n*m+1,T=5*n*m+2;
for(int i=1;i<=n;++i) { // 建立通用边
for(int j=1;j<=m;++j) {
id=m*(i-1)+(j-1);
if((i+j)&1) { // 源点
if(i>1) add(5*id+1,5*(id-m)+3,1,0);
if(i<n) add(5*id+3,5*(id+m)+1,1,0);
if(j>1) add(5*id+4,5*(id-1)+2,1,0);
if(j<m) add(5*id+2,5*(id+1)+4,1,0);
add(S,5*id+5,INF,0);
}else add(5*id+5,T,INF,0);
}
}
bool flg=0;int vis=0;
auto fadd = [&](int u,int v,int w,int c) -> void {
if(flg) add(u,v,w,c);
else add(v,u,w,c);
};
auto calc = [&](int id,int lst,int now,int cost) -> void {
int from=(lst&(~now)),to=((~lst)&now);
if(__builtin_popcount(from)!=1) return;
if((vis&from) || (to&lst)) return;
vis|=from;
fadd(5*id+__builtin_ffs(from),5*id+__builtin_ffs(to),1,cost);
};
int cnt=0;
for(int i=1;i<=n;++i) {
for(int j=1;j<=m;++j) {
flg=(i+j)&1,vis=0,id=m*(i-1)+(j-1);
calc(id,arr[i][j],rorate_r(arr[i][j]),1);
calc(id,arr[i][j],rorate_l(arr[i][j]),1);
calc(id,arr[i][j],rorate_r(rorate_r(arr[i][j])),2);
for(int k=1;k<=4;++k)
if((1<<(k-1))&arr[i][j])
fadd(5*id+5,5*id+k,1,0),++cnt;
}
}
int flow=0;
while(SPFA()) {
flow+=dfs(S,INF);
}
// cout << cnt << ' ' << flow << ' ' << ans << endl;
if(flow*2==cnt) cout << ans;
else cout << -1;
return 0;
}
求调/kel