列表

详情


NC17353. Maxflow

描述

    最近新发售了一款游戏《锡拉丘兹:成为农王》。它并没有什么难度,是一个步行模拟类的游戏。该游戏中共有n个地点和m条道路,每条道路均为双向,连接两个不同的地点。每玩一遍游戏,玩家必须从起点x开始,经过若干地点(不可重复),到达终点y(y与x不同)。玩家在玩的过程中,就可以欣赏图中经过的道路上的风景。一般地,玩家无法在一次游戏中看到所有的风景,所以他可能会玩多次。但是玩家缺乏耐心,无论他玩多少次游戏,他都拒绝经过同一条道路两次,以避免看到重复的风景。从不同的方向经过同一条道路也是不被允许的。现在作为游戏的开发商,你想询问这样一个玩家最多可能玩多少次游戏。你会假定若干组不同的起终点x和y。

输入描述

第一行两个正整数n(1≤n≤100,000)和m(1≤m≤n+100)表示图的点数和边数。
接下来m行每行两个正整数a和b(1≤a,b≤n)表示图中的m条边。保证是连通简单图。
接下来一行一个正整数Q(1≤Q≤100,000)表示询问的组数。
接下来Q行每行两个不同的正整数x和y(1≤x,y≤n)表示一组询问。

输出描述

对于每组询问输出一行,表示在给定的起终点情况下,玩家最多玩多少次游戏。

示例1

输入:

9 10
1 2
2 3
3 4
4 5
5 6
6 7
7 8
8 1
1 9
9 5
2
1 5
2 6

输出:

3
2

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++11(clang++ 3.9) 解法, 执行用时: 88ms, 内存消耗: 8280K, 提交时间: 2018-08-07 15:47:42

#include<cstdio>
#include<vector>
const int maxn=100010,maxm=210000,maxv=210;
struct Edge{int to,cap;Edge*rev,*next;};
struct Graph{
	int n;
	Edge E[maxm],*ne,*fir[maxn];
	void init(int n){ne=E;for(int i=this->n=n;i>=0;i--)fir[i]=0;}
	void link(int a,int b,int c=1){
		*ne=(Edge){b,c,ne+1,fir[a]};fir[a]=ne++;
		*ne=(Edge){a,c,ne-1,fir[b]};fir[b]=ne++;
	}
}G1,G2,T;
int dfn[maxn],low[maxn],now,stk[maxn],top,bcc[maxn];
void cmin(int&a,int b){b<a?a=b:1;}
void dfs1(int i,int f){
	dfn[i]=low[i]=++now;
	stk[top++]=i;
	for(Edge*e=G1.fir[i];e;e=e->next){
		if(!dfn[e->to]){
			dfs1(e->to,i);
			cmin(low[i],low[e->to]);
		}
		else if(e->to!=f)cmin(low[i],dfn[e->to]);
	}
	if(low[i]==dfn[i]){
		do bcc[stk[--top]]=i;
		while(stk[top]!=i);
	}
}
int id[maxn],tot;
void dfs2(int s,int i,int f){
	if(id[i])id[s]<id[i]?G2.link(id[s],id[i]),1:1;
	else for(Edge*e=G1.fir[i];e;e=e->next)if(bcc[e->to]==bcc[i]&&e->to!=f)dfs2(s,e->to,i);
}
Edge*cur[maxv];
int Q[maxv],D[maxv];
int dfs(int i,int t,int c){
	if(i==t||!c)return c;
	int fl=0,f;
	for(Edge*&e=cur[i];e&&c;e=e->next)
		if(e->cap&&D[e->to]==D[i]-1&&(f=dfs(e->to,t,c<e->cap?c:e->cap)))
			fl+=f,e->cap-=f,e->rev->cap+=f,c-=f;
	return fl;
}
int mf(int s,int t){
	for(int f=0;;f+=dfs(s,t,1<<30)){
		for(int i=0;i<=G2.n;i++)D[i]=0,cur[i]=G2.fir[i];
		for(int*H=Q,*T=Q+(D[*Q=t]=1);H<T;H++)
			for(Edge*e=G2.fir[*H];e;e=e->next)
				if(e->rev->cap&&!D[e->to])D[*T++=e->to]=D[*H]+1;
		if(!D[s])return f;
	}
}
void solve(std::vector<int>V){
	if(V.size()<2)return;
	for(Edge*e=G2.E;e<G2.ne;e++)e->cap=1;
	T.link(V[0],V[1],mf(V[0],V[1]));
	std::vector<int>V0,V1;
	for(int i=0;i<V.size();i++)D[V[i]]?V1.push_back(V[i]):V0.push_back(V[i]);
	solve(V0);
	solve(V1);
}
int f[maxv][maxv];
void dfs_t(int s,int i,int fa,int v){
	f[s][i]=v;
	for(Edge*e=T.fir[i];e;e=e->next)
		if(e->to!=fa)dfs_t(s,e->to,i,v<e->cap?v:e->cap);
}
int main(){
	int n,m;
	scanf("%d%d",&n,&m);
	G1.init(n);
	for(int i=0;i<m;i++){
		int a,b;
		scanf("%d%d",&a,&b);
		G1.link(a,b);
	}
	dfs1(1,0);
	std::vector<int>V;
	for(int i=1;i<=n;i++){
		int d=0;
		for(Edge*e=G1.fir[i];e;e=e->next)if(bcc[e->to]==bcc[i])d++;
		if(d>2)V.push_back(id[i]=++tot);
	}
	G2.init(tot);
	T.init(tot);
	for(int i=1;i<=n;i++)if(id[i])
		for(Edge*e=G1.fir[i];e;e=e->next)if(bcc[e->to]==bcc[i])dfs2(i,e->to,i);
	solve(V);
	for(int i=1;i<=tot;i++)dfs_t(i,i,i,1<<30);
	int Q;
	scanf("%d",&Q);
	while(Q--){
		int x,y;
		scanf("%d%d",&x,&y);
		printf("%d\n",bcc[x]!=bcc[y]?1:id[x]&&id[y]?f[id[x]][id[y]]:2);
	}
}

上一题