zoukankan      html  css  js  c++  java
  • 【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 imes (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<<"
    ";
    	return 0;
    }
    
    
  • 相关阅读:
    Windows系统结构
    Windows系统基本概念
    基本NT式驱动代码结构
    数据切割
    虚函数
    基类和派生类:谈继承
    jQuery简单的上拉加载
    检测是否为数组
    倒计时案例分析
    获得总的毫秒数
  • 原文地址:https://www.cnblogs.com/hchhch233/p/10582425.html
Copyright © 2011-2022 走看看