Description

题面

题目大意:求一个排列 \(P\),使得 \(\sum_{i=1}^{n-1}maxflow(P_i,P_{i+1})\) 尽量大

Solution

构造出最小割树,那么第一问答案就是最小割树的边权和

之前我对最小割树都理解错了

实际上这么一个过程:

1.从当前集合中任选两个点 \((x,y)\) 作为源汇点,跑最小割,然后连边 \((x,y,maxflow)\)

2.把原集合由割边分为两个集合,递归处理,并且要把上一个集合的 \(T\),作为这个集合的 \(S\) ,这样才能保证连成一棵树

3.直到点集只有一个点时,返回

构出来的树满足性质:

原图中 \((x,y)\) 的最小割,就是树中 \((x,y)\) 路径中的最小边权

然后考虑如何构造一种方案使得最大流之和最大

首先我们肯定要让最小边走最少的次数,那么我们就只需要尽量不经过这条边就可以了(因为这条边权值是最小的,所以经过了就一定会算一次这条边的贡献)

于是就产生了这么一个做法:

找到权值最小边,把这条边断开分为两个集合,继续递归,直到集合大小为\(1\)时,我们把点加入到排列中

这样排列中的点就分为了两部分 \((x1,x2,x3..xn)\),\((y1,y2,y3...yn)\),\(x,y\) 分别对应这条边两端的点的集合

这样做下去,边权小的边经过的次数我们已经最小化了,但是发现还是不可避免的会经过一次

所以我们得出结论:所有的边都恰好经过一次,这样就得到了第一问的答案

第二问的答案也可以通过模拟这个过程得出

#include<bits/stdc++.h>
#define pb push_back
using namespace std;
const int N=205,M=4005,inf=2e8;
struct sub{int x,y,z;}e[M];int b[N];
int n,m,id[N],dep[N],S,T,head[N],nxt[M],to[M],dis[M];
int num=1,ans=0,Head[N],NUM=1,TO[M],DIS[M]={inf},NXT[M];
inline void link(int x,int y,int z){
nxt[++num]=head[x];to[num]=y;head[x]=num;dis[num]=z;
nxt[++num]=head[y];to[num]=x;head[y]=num;dis[num]=z;
}
inline void Link(int x,int y,int z){
NXT[++NUM]=Head[x];TO[NUM]=y;Head[x]=NUM;DIS[NUM]=z;
NXT[++NUM]=Head[y];TO[NUM]=x;Head[y]=NUM;DIS[NUM]=z;
}
inline bool bfs(){
queue<int>Q;
memset(dep,0,sizeof(dep));
dep[S]=1;Q.push(S);
while(!Q.empty()){
int x=Q.front();Q.pop();
for(int i=head[x];i;i=nxt[i]){
int u=to[i];
if(dep[u] || dis[i]<=0)continue;
dep[u]=dep[x]+1;Q.push(u);
}
}
return dep[T];
}
inline int dfs(int x,int flow){
if(x==T || !flow)return flow;
int u,tmp,tot=0;
for(int i=head[x];i;i=nxt[i]){
u=to[i];
if(dep[u]!=dep[x]+1 || dis[i]<=0)continue;
tmp=dfs(u,min(flow,dis[i]));
dis[i]-=tmp;dis[i^1]+=tmp;
flow-=tmp;tot+=tmp;
if(!flow)break;
}
if(!tot)dep[x]=-1;
return tot;
}
inline int maxflow(int tx,int ty){
S=tx;T=ty;
int tot=0,t;
while(bfs()){
t=dfs(S,inf);
while(t)tot+=t,t=dfs(S,inf);
}
return tot;
}
inline void Clear(){memset(head,0,sizeof(head));num=1;}
inline void solve(int l,int r){
if(l==r)return ;
Clear();
for(int i=1;i<=m;i++)link(e[i].x,e[i].y,e[i].z);
int t=maxflow(id[l],id[r]),L=l-1,R=r+1;
ans+=t;Link(id[l],id[r],t);
for(int i=l;i<=r;i++)
if(dep[id[i]])b[++L]=id[i];else b[--R]=id[i];
reverse(b+L+1,b+R+1); //为了保证形成一棵树,id[r] 这个点必须作为下一层的 id[l]
for(int i=l;i<=r;i++)id[i]=b[i];
solve(l,L);solve(R,r);
}
bool vis[M];int maxid=0;
inline void BFS(int x,int last){
for(int i=Head[x];i;i=NXT[i]){
if(TO[i]==last || vis[i])continue;
if(DIS[i]<DIS[maxid])maxid=i;
BFS(TO[i],x);
}
}
inline void Deal(int x){
maxid=0;BFS(x,x);
if(maxid==0){printf("%d ",x);return ;}
vis[maxid]=vis[maxid^1]=1;
int u=TO[maxid],v=TO[maxid^1];
Deal(u);Deal(v);
}
int main(){
freopen("pp.in","r",stdin);
freopen("pp.out","w",stdout);
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].z);
for(int i=1;i<=n;i++)id[i]=i;
solve(1,n);
printf("%d\n",ans);
Deal(1);
return 0;
}

Codeforces 343E Pumping Stations的更多相关文章

  1. CodeForces - 796D Police Stations bfs

    思路:删除尽量多的边使得所有点都能在限制距离之内到达一个警局,删除边会形成多棵子树,最多只能k棵.其实就是以每个警局为根结点,把整棵树划分为以警局为根结点的k棵树,说明要删除的边的数量就是k-1条,即 ...

  2. CF343E Pumping Stations(最小割树)

    没学过最小割树的出门左转. 我们已经知道了两点的最小割就是最小割树上,对应两点之间路径的权值的最小值. 找到最小割树中权值的最小的边. 那么一定是先选完一侧的点在选完另一侧的点. 因为当前边最小,那么 ...

  3. Codeforces 1215F. Radio Stations

    传送门 题目看一半:"woc 裸的 $2-sat$ 白给??" 看完以后:"...???" 如果没有 $f$ 的限制,那就是个白给的 $2-sat$ 问题,但是 ...

  4. Codeforces 343E 最小割树

    题意及思路:https://www.cnblogs.com/Yuzao/p/8494024.html 最小割树的实现参考了这篇博客:https://www.cnblogs.com/coder-Uran ...

  5. Codeforces Round #200 (Div. 1 + Div. 2)

    A. Magnets 模拟. B. Simple Molecules 设12.13.23边的条数,列出三个等式,解即可. C. Rational Resistance 题目每次扩展的电阻之一是1Ω的, ...

  6. mark一下咕掉的题目

    蒟蒻才普及组呀~ 大佬别D我 等集中补一下 CF980F:咋说捏,我觉得要联赛了做这题有点浪费时间,等想颓废了再来写写叭qwq 215E/279D/288E/331C3/431D/433E/750G/ ...

  7. Codeforces Round #408 (Div. 2) D - Police Stations

    地址:http://codeforces.com/contest/796/problem/D 题目: D. Police Stations time limit per test 2 seconds ...

  8. CodeForces - 762E:Radio stations (CDQ分治||排序二分)

    In the lattice points of the coordinate line there are n radio stations, the i-th of which is descri ...

  9. 【codeforces 796D】Police Stations

    [题目链接]:http://codeforces.com/contest/796/problem/D [题意] 在一棵树上,保证每个点在距离d之内都有一个警察局; 让你删掉最多的边,使得剩下的森林仍然 ...

随机推荐

  1. beta冲刺7-咸鱼

    前言:最后一篇惹.明天就是正式交差了.有点慌-- 昨天的未完成: 用户试用+测评 输入部分的正则式判定 今天的工作: 登陆界面修改 我的社团显示效果优化 部分信息注册后锁定无法修改 其他部分功能优化 ...

  2. beta冲刺2-咸鱼

    q前言:今天晚上大概把github的的相关东西弄上了.然后把之前做的一些修改什么的也上传上去了.目测之后的话就是在自己这边改完然后直接上github那边去复制粘贴替换掉了. 昨天的问题:github这 ...

  3. C语言博客-指针

    一.PTA实验作业(5分) 题目1:6-1 两个4位正整数的后两位互换 1. 本题PTA提交列表 2. 设计思路 3.代码截图 4.本题调试过程碰到问题及PTA提交列表情况说明. 无 题目2:6-3 ...

  4. 敏捷冲刺每日报告——Day4

    1.情况简述 Alpha阶段第一次Scrum Meeting 敏捷开发起止时间 2017.10.28 00:00 -- 2017.10.29 00:00 讨论时间地点 2017.10.28晚9:30, ...

  5. Beta阶段总结分析报告

    1 讨论照片 2 Postmortem结果 二手交易平台项目Postmortem结果 整理:程环宇 设想和目标 1.       我们的软件要解决什么问题?是否定义得很清楚?是否对典型用户和典型场景有 ...

  6. 1013团队Beta冲刺day3

    项目进展 李明皇 今天解决的进度 完善了程序的运行逻辑(消息提示框等) 明天安排 前后端联动调试 林翔 今天解决的进度 向微信官方申请登录验证session以维护登录态 明天安排 继续完成维护登录态 ...

  7. C语言--第二周作业

    ****学习内容总结**** 1.Git和编辑器截图 2.MOOC截图 3.阅读<提问的智慧>感想 读完<提问的智慧>之后,我认为在提问时,要根据以下步骤: 谨慎明确的描述症状 ...

  8. 201621123057 《Java程序设计》第9周学习总结

    1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结集合与泛型相关内容. 在上一周的总结上做了一点补充 1.2 选做:收集你认为有用的代码片段 2. 书面作业 本次作业题集集合 1. ...

  9. 项目Beta冲刺Day1

    项目进展 李明皇 今天解决的进度 点击首页list相应条目将信息传到详情页 明天安排 优化信息详情页布局 林翔 今天解决的进度 前后端连接成功 明天安排 开始微信前端+数据库写入 孙敏铭 今天解决的进 ...

  10. JS中的 map, filter, some, every, forEach, for...in, for...of 用法总结

    1.map 有返回值,返回一个新的数组,每个元素为调用func的结果. let list = [1, 2, 3, 4, 5]; let other = list.map((d, i) => { ...