【FJWC 2019】min
【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的更多相关文章
- 【FJWC 2019】 森林
[FJWC 2019] 森林 样例输入 0 5 1 0 0 2 样例输出 1 2 3 3 我们发现,答案就是直径加上直径上某个点出发,不经过其他直径上的点的最长链.这里的直径可以是任意一条直径. 首先 ...
- 【等价转换】—— 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 ...
- 【ZJOI 2019】麻将(dp of dp)
这是我第一次写$dp \; of \; dp$,大致思路参考了xyx的做法,可能有些地方不太一样,但也许会详细一点. 考虑给你一副牌,如何判断这副牌是否是胡的. 容易发现相同的顺子不会选三个以上,于是 ...
- 【GZOI 2019】特技飞行
Problem Description 公元 \(9012\) 年,Z 市的航空基地计划举行一场特技飞行表演.表演的场地可以看作一个二维平面直角坐标系,其中横坐标代表着水平位置,纵坐标代表着飞行高度. ...
- 【HNOI 2019】JOJO
Problem Description JOJO 的奇幻冒险是一部非常火的漫画.漫画中的男主角经常喜欢连续喊很多的「欧拉」或者「木大」. 为了防止字太多挡住漫画内容,现在打算在新的漫画中用 \(x\) ...
- 【CSP-SJX 2019】T4 散步
Description 传送门 Solution 算法1 32pts 枚举每个时刻,并枚举所有发生的时间,暴力进行更新.发现最多只需要枚举到第 \(L\)个时刻,因为是一个环,所以最多到第L个时刻,所 ...
- 【CSP-S 2019】D2T2 划分
Description 传送门 Solution 算法1 12pts 指数算法随便乱搞. 算法2 36pts \(O(n^3)\)dp. 设\(f_{i,j}\)表示以位置\(j\)结尾,上一个决策点 ...
- 【JOISC2019|2019】【20190622】cake3
题目 \(N\) 个物品中选\(M\)个,排列成一个环:\(k_1,\cdots,k_M\)价值为: \[ \sum_{j=1}^{N}{V_i} - \sum_{j=1}^{M}|C_{k_j}- ...
- 【CSP-S 2019】【洛谷P5665】划分【单调队列dp】
前言 \(csp\)时发现自己做过类似这道题的题目 : P4954 [USACO09Open] Tower of Hay 干草塔 然后回忆了差不多\(15min\)才想出来... 然后就敲了\(88p ...
随机推荐
- mysql+高可用MMM
一. MMM 简介:MMM 即 Multi-Master Replication Manager for MySQL:mysql 多主复制管理器,基于 perl 实现,关于 mysql 主主复制配置的 ...
- 原创SQlServer数据库生成简单的说明文档包含(存储过程、视图、数据库批量备份)小工具(附源码)
这是一款简单的数据库文档生成工具,主要实现了SQlServer生成说明文档的小工具,目前不够完善,主要可以把数据库的表以及表的详细字段信息,导出到 Word中,可以方便开发人员了解数据库的信息或写技术 ...
- python使用gevent实现并发下载器
并发下载原理 import gevent from gevent import monkey import urllib.request monkey.patch_all() def my_downl ...
- Javascript继承4:洁净的继承者----原型式继承
//原型式继承 function inheritObj(obj){ //声明一个过渡函数对象 function F(){} //过渡对象的原型继承父对象 F.prototype = obj; //返回 ...
- 教你搞定ElasticSearch(head)
简介: ElasticSearch(以下简称ES)是一个基于Lucene构建的开源(open-source),分布式(distributed),RESTful,实时(real-time)的搜索与分析( ...
- mybatis全局属性(全局变量)
mybatis全局属性(全局变量):方法1:在 properties 元素体内,使用<property>标签定义的属性方法2:在 properties 元素中, 使用 resource 或 ...
- ecstore Fatal error: Class 'base_request' not found
1.首次安装已存在的ecstore报错: Fatal error: Class 'base_request' not found 报错效果图:(ecstore 乱码需要安装zend guard loa ...
- lnmp环境切换php版本,并安装相应redis扩展
ubuntu+nginx+mysql+php+redis,其中php装两个版本,php7和php56 1.让nginx支持不同站点可以选择不同的php版本 1>创建fastcgi.conf文件 ...
- js实现本地图片文件拖拽效果
如何拖拽图片到指定位置,具体方法如下 在从本地上传图片的时候,如果使用拖拽效果,想想应该是更加的高大上,下面直接上js代码 完整代码: ? 1 2 3 4 5 6 7 8 9 10 11 12 13 ...
- GDPR 和个人信息保护的小知识
从2018年5月25日起,欧盟的<通用数据保护条例>(简称 GDPR,General Data Protection Regulation)开始强制施行.这个规范加强了对个人信息的保护,并 ...