BZOJ4124 : [Baltic2015]Tug of war
建立二分图,首先如果存在度数为00的点,那么显然无解。
如果存在度数为11的点,那么这个点的匹配方案固定,可以通过拓扑排序去掉所有这种点。
那么现在剩下的点度数都至少为22,因为左右点数相等,且左边每个点度数都是22,所以右边只能是每个点的度数都是22。
在这种情况下每个连通块是一个环,相邻两条边不能同时选,一共有两种情况xx和yy。
假设x≤yx≤y,那么把xx加入sumsum,y−xy−x既可以加入,又可以不加入,对y−xy−x进行01背包即可。
注意到本题中物品数不超过2n2n,物品价值之和不超过2k≤40n2k≤40n。
所以将01背包转化为多重背包后只有O(√k)O(√k)种物品,二进制拆分+bitset优化即可。
时间复杂度O(k√klogk64)O(k√klogk64)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | #include<cstdio> #include<bitset> #include<algorithm> using namespace std; const int N=120010,M=1200010; int n,m,K,i,j,k,x,y,z,g[N],v[N<<1],w[N<<1],nxt[N<<1],ed,d[N],h,t,q[N],vis[N],sum,cnt[M]; bitset<M>f; inline void read( int &a){ char c; while (!(((c= getchar ())>= '0' )&&(c<= '9' )));a=c- '0' ; while (((c= getchar ())>= '0' )&&(c<= '9' ))(a*=10)+=c- '0' ;} inline void add( int x, int y, int z){ d[x]++,d[y]++; v[++ed]=y;w[ed]=z;nxt[ed]=g[x];g[x]=ed; v[++ed]=x;w[ed]=z;nxt[ed]=g[y];g[y]=ed; } inline int go( int x){ for ( int i=g[x];i;i=nxt[i]) if (!vis[v[i]]) return v[i]; return 0; } inline int get( int x, int y){ for ( int i=g[x];i;i=nxt[i]) if (v[i]==y) return w[i];} int main(){ read(n),read(K);m=n+n; for (i=1;i<=m;i++){ read(x),read(y),read(z); add(i,x+m,z); add(i,y+n+m,-z); } m<<=1; for (i=1;i<=m;i++) if (!d[i]) return puts ( "NO" ),0; for (h=i=1;i<=m;i++) if (d[i]==1)q[++t]=i; while (h<=t){ for (i=g[x=q[h++]];i;i=nxt[i]) if (!vis[v[i]]){ y=v[i]; sum+=w[i]; break ; } vis[x]=vis[y]=1; for (i=g[y];i;i=nxt[i]) if (!vis[x=v[i]]){ if (!(--d[x])) return puts ( "NO" ),0; if (d[x]==1)q[++t]=x; } } for (n=0,i=1;i<=m;i++) if (!vis[i]){ vis[q[t=1]=i]=1; for (j=go(i);j;j=go(j))vis[q[++t]=j]=1; q[t+1]=q[1]; x=y=0; for (j=1;j<=t;j+=2)x+=get(q[j],q[j+1]); for (j=2;j<=t;j+=2)y+=get(q[j],q[j+1]); if (x>y)swap(x,y); sum+=x; cnt[y-x]++; n=max(n,y-x); } for (f[0]=i=1;i<=n;i++) for (j=1;cnt[i];j<<=1){ k=min(cnt[i],j); cnt[i]-=k; f|=f<<(i*k); } for (i=-K;i<=K;i++) if (i-sum>=0&&i-sum<M) if (f[i-sum]) return puts ( "YES" ),0; return puts ( "NO" ),0; } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 25岁的心里话
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现