【FJWC 2019】min

题目描述

给你一张 \(n\) 个点 \(m\) 条边的无向图,走过每条边都需要花费 \(1\) 秒。

给你一个整数 \(k\) ,请你选择至多 \(k\) 个点,令经过这些点也需要花费 \(1\) 秒,使得从点 \(0\) 走到点 \(n-1\) 的最短时间最大。输出这个最大值。

注意,不能选择点 \(0\) 或点 \(n-1\) 。

输入格式

第一行三个正整数 \(n,m,k\) ,意义见题面描述。

接下来 \(m\) 行,每行两个数 \(x,y\) ,表示 \(x\) 和 \(y\) 之间存在一条边,保证 \(0 \le x,y < n\) ,不存在重边和自环,且点 \(0\) 和点 \(n-1\) 连通。

样例输入

3 2 1

0 1

1 2

样例输出

3

\(2 \le n \le 100,1 \le m \le n \times (n-1)/2,0 \le k \le n\)

感觉对网络流相关知识太不熟练了,这种题都要写自闭。

题解二分有点神仙。

我的做法复杂度就不那么优秀了。首先找到最短路,然后我们要求出选最少的点使得\(0\)到\(n-1\)最短路\(+1\)。我们很容易发现就是要选出最少的点割断使得\(0\)和\(n-1\)不连通。

网络流啊!

每个点拆成两个,流量为一,其他在最短路上的边也要连上,流量\(\infty\)。

我们每次做完网络流过后随便求出一个最小割集,这些点就是我们选的点。然后我们重新跑最短路,重新建图。那些选了的点之间流量\(\infty\),因为这些点不能再割了。

我们重复做,直到所有点选完或者\(k\)个点用完为止。

找出仍以一组最小割只需要从源点\(S\)出发,走富余边\(dfs\)一遍,得到点集\(\{S\}\)。如果一条满流边一个点\(\in\{S\}\),另一个不属于,那么这就是我们要选的点。

然而我智障地写了\(tarjan\)还有退流操作。。

代码:

#include<bits/stdc++.h>
#define ll long long
#define N 205 using namespace std;
inline int Get() {int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}while('0'<=ch&&ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}return x*f;} int n,m,k;
struct road {
int to,next;
}s[N*N<<2];
int h[N],cnt;
void add(int i,int j) {s[++cnt]=(road) {j,h[i]};h[i]=cnt;}
int dis[N];
bool del[N];
struct node {
int v,d;
node() {v=d=0;}
node(int a,int b) {v=a,d=b;}
bool operator <(const node &a)const {
return d>a.d;
}
}; priority_queue<node>Q;
void dij() {
static bool in[N];
memset(dis,0x3f,sizeof(dis));
memset(in,0,sizeof(in));
dis[1]=0;
Q.push(node(1,0));
while(!Q.empty()) {
int v=Q.top().v;
Q.pop();
if(in[v]) continue ;
in[v]=1;
for(int i=h[v];i;i=s[i].next) {
int to=s[i].to;
if(in[to]) continue ;
if(dis[to]>dis[v]+1+del[to]) {
dis[to]=dis[v]+1+del[to];
Q.push(node(to,dis[to]));
}
}
}
} int ans;
namespace dinic {
struct road {int to,next,f;}s[N*N<<2];
int h[N<<1],cnt=1;
int id[N];
void add(int i,int j,int f) {
s[++cnt]=(road) {j,h[i],f};h[i]=cnt;
s[++cnt]=(road) {i,h[j],0};h[j]=cnt;
}
int S,T;
int dis[N];
queue<int>q;
bool bfs(int S,int T) {
memset(dis,0x3f,sizeof(dis));
q.push(S);
dis[S]=0;
while(!q.empty()) {
int v=q.front();q.pop();
for(int i=h[v];i;i=s[i].next) {
int to=s[i].to;
if(s[i].f&&dis[to]>dis[v]+1) {
dis[to]=dis[v]+1;
q.push(to);
}
}
}
return dis[T]<1e9;
}
int dfs(int v,int maxf) {
if(v==T) return maxf;
int ret=0;
for(int i=h[v];i;i=s[i].next) {
int to=s[i].to;
if(s[i].f&&dis[to]==dis[v]+1) {
int dlt=dfs(to,min(maxf,s[i].f));
ret+=dlt;
s[i].f-=dlt;
s[i^1].f+=dlt;
maxf-=dlt;
if(!maxf) return ret;
}
}
return ret;
}
int dinic() {
int ans=0;
while(bfs(S,T)) {
while(1) {
int tem=dfs(S,1e9);
if(!tem) break ;
ans+=tem;
if(ans>=1e9) return ans;
}
}
return ans;
}
int dfn[N],low[N],tot;
int st[N],bel[N],scc;
bool ins[N];
void tarjan(int v) {
low[v]=dfn[v]=++tot;
ins[v]=1;
st[++st[0]]=v;
for(int i=h[v];i;i=s[i].next) {
int to=s[i].to;
if(!s[i].f) continue ;
if(!dfn[to]) {
tarjan(to);
low[v]=min(low[v],low[to]);
} else if(ins[to]) low[v]=min(low[v],dfn[to]);
}
if(dfn[v]==low[v]) {
scc++;
while(1) {
int j=st[st[0]--];
bel[j]=scc;
ins[j]=0;
if(j==v) break;
}
}
}
void Init() {
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
memset(ins,0,sizeof(ins));
memset(bel,0,sizeof(bel));
tot=scc=0;
}
void Tarjan() {
Init();
for(int i=1;i<2*n;i++)
if(!dfn[i]&&i!=n+1) tarjan(i);
}
vector<int>tem;
bool dfs(int v) {
if(v==T) return 1;
for(int i=h[v];i;i=s[i].next) {
int to=s[i].to;
if(s[i].f&&dfs(to)) return 1;
}
return 0;
}
void Cut() {
Tarjan();
tem.clear();
for(int i=2;i<n;i++) {
if(s[id[i]].f) continue ;
if(bel[i]!=bel[i+n]) {
S=i,T=1;
dinic();
S=n,T=i+n;
dinic();
tem.push_back(i);
del[i]=1;
s[id[i]].f=s[id[i]^1].f=0;
S=1,T=n;
dinic();
Tarjan();
}
}
}
void build() {
cnt=1;
memset(h,0,sizeof(h));
for(int i=2;i<n;i++) {
if(del[i]) add(i,i+n,1e9);
else add(i,i+n,1);
}
for(int v=1;v<n;v++) {
for(int i=::h[v];i;i=::s[i].next) {
int to=::s[i].to;
if(::dis[to]==::dis[v]+1+del[to]) {
if(v>1) add(v+n,to,1e9);
else add(v,to,1e9);
}
}
}
}
void solve() {
int res=k;
int tim=0;
while(1) {
S=1,T=n;
int now=dinic();
if(res<now) return ;
res-=now;
ans++;
Cut();
dij();
build();
}
return ;
}
} int main() {
n=Get(),m=Get(),k=Get();
int a,b;
for(int i=1;i<=m;i++) {
a=Get()+1,b=Get()+1;
add(a,b),add(b,a);
}
dij();
for(int i=2;i<n;i++) {
dinic::id[i]=dinic::cnt+1;
dinic::add(i,i+n,1);
}
for(int v=1;v<n;v++) {
for(int i=h[v];i;i=s[i].next) {
int to=s[i].to;
if(dis[to]==dis[v]+1) {
if(v>1) dinic::add(v+n,to,1e9);
else dinic::add(v,to,1e9);
}
}
}
ans=dis[n];
dinic::solve();
cout<<ans<<"\n";
return 0;
}

【FJWC 2019】min的更多相关文章

  1. 【FJWC 2019】 森林

    [FJWC 2019] 森林 样例输入 0 5 1 0 0 2 样例输出 1 2 3 3 我们发现,答案就是直径加上直径上某个点出发,不经过其他直径上的点的最长链.这里的直径可以是任意一条直径. 首先 ...

  2. 【等价转换】—— min/max 的转换与互相转换

    0. min 与 max 的转换 {max(X,Y)=X+Y−min(X,Y)min(X,Y)=X+Y−max(X,Y)min(X,Y)+max(X,Y)=X+Y" role="p ...

  3. 【ZJOI 2019】麻将(dp of dp)

    这是我第一次写$dp \; of \; dp$,大致思路参考了xyx的做法,可能有些地方不太一样,但也许会详细一点. 考虑给你一副牌,如何判断这副牌是否是胡的. 容易发现相同的顺子不会选三个以上,于是 ...

  4. 【GZOI 2019】特技飞行

    Problem Description 公元 \(9012\) 年,Z 市的航空基地计划举行一场特技飞行表演.表演的场地可以看作一个二维平面直角坐标系,其中横坐标代表着水平位置,纵坐标代表着飞行高度. ...

  5. 【HNOI 2019】JOJO

    Problem Description JOJO 的奇幻冒险是一部非常火的漫画.漫画中的男主角经常喜欢连续喊很多的「欧拉」或者「木大」. 为了防止字太多挡住漫画内容,现在打算在新的漫画中用 \(x\) ...

  6. 【CSP-SJX 2019】T4 散步

    Description 传送门 Solution 算法1 32pts 枚举每个时刻,并枚举所有发生的时间,暴力进行更新.发现最多只需要枚举到第 \(L\)个时刻,因为是一个环,所以最多到第L个时刻,所 ...

  7. 【CSP-S 2019】D2T2 划分

    Description 传送门 Solution 算法1 12pts 指数算法随便乱搞. 算法2 36pts \(O(n^3)\)dp. 设\(f_{i,j}\)表示以位置\(j\)结尾,上一个决策点 ...

  8. 【JOISC2019|2019】【20190622】cake3

    题目 \(N\) 个物品中选\(M\)个,排列成一个环:\(k_1,\cdots,k_M\)价值为: \[ \sum_{j=1}^{N}{V_i} - \sum_{j=1}^{M}|C_{k_j}- ...

  9. 【CSP-S 2019】【洛谷P5665】划分【单调队列dp】

    前言 \(csp\)时发现自己做过类似这道题的题目 : P4954 [USACO09Open] Tower of Hay 干草塔 然后回忆了差不多\(15min\)才想出来... 然后就敲了\(88p ...

随机推荐

  1. EF(EntityFramework)与mysql使用,错误终极解决方案

    我昨天写了好多篇跟mysql有关的错误,但是在今天我发现好像所有的问题都是一个原因引起的: 版本问题,我原先使用的是MySql.Data.Entity.EF6(版本号:6.10.5),今天我换成6.9 ...

  2. html 三列布局(两列自适应,一列固定宽度)

    不做过多解释:主要是记录一个完整的布局样式,实现页面大致三列其中左右两列是自适应宽度,中间固定宽度效果. 不多少代码奉上: CSS样式代码: /******************** *公共标签样式 ...

  3. 推送GitHub报错 fatal: Out of memory, malloc failed 解决办法

    现象: 推送GitHub时,出现如下报错 fatal: Out of memory, malloc failed (tried to allocate XXXXXX bytes)error: fail ...

  4. C#设计模式之十五迭代器模式(Iterator Pattern)【行为型】

    一.引言 今天我们开始讲“行为型”设计模式的第三个模式,该模式是[迭代器模式],英文名称是:Iterator Pattern.还是老套路,先从名字上来看看.“迭代器模式”我第一次看到这个名称,我的理解 ...

  5. Flask 系列之 LoginManager

    说明 操作系统:Windows 10 Python 版本:3.7x 虚拟环境管理器:virtualenv 代码编辑器:VS Code 实验目标 通过使用 flask-login 进行会话管理的相关操作 ...

  6. 异常: The server time zone value 'Öйú±ê׼ʱ¼ä' is unrecognized or represents more than one time zone. You must configure either the server or JDBC driver (via the serverTimezone configurat

    异常: The server time zone value 'Öйú±ê׼ʱ¼ä' is unrecognized or represents more than one time zone. ...

  7. js对象工厂函数与构造函数

    转自:http://www.cnblogs.com/Jener/p/5920963.html ★概述:         使用对象字面量,或者向空对象中动态地添加新成员,是最简单易用的对象创建方法.然而 ...

  8. html5基础!!

    A:HTML5 不基于 SGML,所以不需要引用 DTD: B: HTML 4.01 基于 SGML,而HTML5不基于SGML: DTD可定义合法的XML文档构建模块,它使用一系列合法的元素来定义文 ...

  9. GitHub for Windows离线安装包

    国内安装github客户端,真的很痛!! 偶然找到了离线安装包,感谢作者的资源分享!!! 地址:http://download.csdn.net/download/lyg468088/8723039? ...

  10. JavaScript面向对象编程指南(六) 继承

    第6章 继承 6.1 原型链 6.1.1原型链示例 原型链法:Child.prototype=new Parent(); <script> function Shape(){ this.n ...