1 条题解
-
0
自动搬运
来自洛谷,原作者为

Timmylyx
努力的小羊 咩~搬运于
2025-08-24 22:45:51,当前版本为作者最后更新于2025-07-10 22:39:40,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
友情提示:本题解 看起来错误,但
本蒟蒻认为是正确的,如有不严谨欢迎各位大佬多多指出。题意
题目说有 种不同型号的木棍,木棍左右各有一个小于 的非负整数,左侧数为 ,右侧数为 的木棍有 个。
现在要把它们 从左到右 拼起来,求问最多有多少对相邻的木棍使得连接他们的两个数的和为 。
题解
看上去没有头绪,
感觉像有源汇上下界最大费用最大流套路而且数据范围很大,所以我们考虑 正难则反。我们把木棍抽象成边,数抽象成点,绘制一张图。(这里就不放了)
然后我们发现这张图不太好用,因为我们没法表示和为 的限制,所以我们考虑把边 变成 (新增点 )。
下图为更改后的图:

那么我们会发现,这张图上每拿掉一条长度为 的路径,答案会增加 。
那么显然我们取完路径之后,,所以我们考虑最少减几个 。
我们设 是每个点的入度, 是每个点的出度,则点 会产生 条“废边”(注意每条废边会被记录两次,记得除 ),那么我们可以考虑以这些废边为起点,假设有 条废边,则答案减 。
这是对的吗?不对!有特殊情况。假设某个连通块内没有废边,但是一条路径一定有起点,这时答案仍要减 。
然后(就没有然后了)……
代码
#include <bits/stdc++.h> using namespace std; #define int long long #define N 1010 int fa[N],r[N],c[N]; int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);} signed main(){ int t; cin>>t; while (t--){ memset(r,0,sizeof(r)); memset(c,0,sizeof(c)); int n,ans=0; cin>>n; for (int i=0; i<=n; i++) fa[i]=i; for (int i=0; i<n; i++){ for (int j=0; j<n; j++){ int x; cin>>x; if (x){ ans+=x; r[i]+=x; c[n-j]+=x; if (find(i)!=find(n-j)){ fa[find(i)]=find(n-j); } } } } for (int i=0; i<=n; i++){ if (find(i)!=i||!c[i]&&!r[i]) continue;//小心空连通块 int sum=0,flag=0; for (int j=0; j<=n; j++) if (find(j)==i) sum+=abs(r[j]-c[j]); ans-=max(sum>>1,1ll); } cout<<ans<<"\n"; } }
- 1
信息
- ID
- 8403
- 时间
- 1000ms
- 内存
- 128MiB
- 难度
- 6
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者