【SHOI2010】最小生成树(最小割,最小生成树)
初看题目,发现题目的操作比较复杂。仔细想了一想,发现题目中的操作“把图中除了这条边以外的边,每一条的权值都减少 ”就等价于“把这条边的权值加 ”。所以题目的操作就被我们化繁为简了。
然后继续想:如何才能使 边一定在最小生成树中?
画个图看一下(就以样例为例):
假设现在 边是 ,长度为 。
那么既然我要保证 边是最小生成树的一条边,点 、 就不能在一个环里面,也就是说,点 、 之间不能存在另一条可选的路径。(注意“边”与“路径”的区别)
也就是说,在原来的无向图上, 的其他路径中,每条路径至少要存在一条边的边权大于 ,否则在建最小生成树时就有可能被选到。
比如 的其他路径有 、 ……,其中路径 是不满足条件的,因为这条路径上没有一条边的边权大于 ,那么我们就有可能选边:
而不是这样:
总而言之,设 边是 ,长度为 ,那么我们要保证在操作之后的无向图上,不存在一条路径 使得这条路径上所有边的边权都小于等于 。
如何维护?
一种显然的暴力就是:枚举 的每一条路径,找到路径上边权的最大值 ,如果 ,就不管它,否则就用 次操作使得这条边权最大的边的权值加上 ,超过 。这时我们就能用最小的代价保证这条路径不可能被选到。
想到这里很容易想到最小割:找到边权 小于等于 的每条边 ,并在另一个图上建边 ,然后再从 到 跑最小割,也就是说找到 每条路径上操作代价最小的一条边。最后跑出来的最小割就是答案。
代码如下:
#include<bits/stdc++.h>
#define N 510
#define M 810
#define INF 0x7fffffff
using namespace std;
struct edge
{
int u,v,w;
}e[M];
int n,m,lab,s,t;
int cnt=1,head[N],cur[N],to[M<<2],nxt[M<<2],c[M<<2];
int num[N];
queue<int>q;
void adde(int u,int v,int ci)
{
to[++cnt]=v;
c[cnt]=ci;
nxt[cnt]=head[u];
head[u]=cnt;
to[++cnt]=u;
c[cnt]=0;
nxt[cnt]=head[v];
head[v]=cnt;
}
bool bfs()
{
memcpy(cur,head,sizeof(cur));
memset(num,-1,sizeof(num));
q.push(s);
num[s]=0;
while(!q.empty())
{
int u=q.front();
q.pop();
for(int i=head[u];i;i=nxt[i])
{
int v=to[i];
if(c[i]&&num[v]==-1)
{
num[v]=num[u]+1;
q.push(v);
}
}
}
return num[t]!=-1;
}
int dfs(int u,int minflow)
{
if(!minflow||u==t) return minflow;
int preflow=0,nowflow;
for(int i=cur[u];i;i=nxt[i])
{
cur[u]=i;
int v=to[i];
if(num[v]==num[u]+1&&(nowflow=dfs(v,min(minflow-preflow,c[i]))))
{
preflow+=nowflow;
c[i]-=nowflow;
c[i^1]+=nowflow;
if(!(minflow-preflow)) break;
}
}
return preflow;
}
int dinic()
{
int maxflow=0;
while(bfs())
maxflow+=dfs(s,INF);
return maxflow;
}
int main()
{
scanf("%d%d%d",&n,&m,&lab);
for(int i=1;i<=m;i++)
scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
s=e[lab].u,t=e[lab].v;
for(int i=1;i<=m;i++)
{
if(i!=lab&&e[i].w<=e[lab].w)
{
adde(e[i].u,e[i].v,e[lab].w-e[i].w+1);//别问我为什么要建双向边,问就是这是dinic,分层图不怕死循环
adde(e[i].v,e[i].u,e[lab].w-e[i].w+1);
}
}
printf("%d\n",dinic());
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现