首页 > 其他分享 >CF700C

CF700C

时间:2024-03-09 10:33:41浏览次数:23  
标签:tarjan cut int d% dfn low CF700C

图论基础题。但是想偏了想了半天。

考虑先对原图做一次 tarjan 求割边。处理 \(c=1\) 的答案。

\(c=2\) 最自然的想法是枚举所有边,断掉,再重新跑 tarjan。但是会超时。但是不难发现,只有 tarjan 建出的 dfs 树上的树边删去时,树的形态有可能改变。

这些边有 \(O(n)\) 个,每个 \(O(n+m)\) 暴力跑。否则拿一个可重集,维护每个点返祖边所指向的点的 dfn,每次删去 \((u,v)\) 边时修改此集合,再 \(O(n)\) 对 dfs 树做一遍 dfs 处理出 tarjan 的 low 即可。

总时间复杂度 \(O(nm)\) 轻松过。

code:

点击查看代码
int n,m,s,t;
int cur,dfn[N],low[N],fa[N];
bool pd[M],vis[M];
multiset<int> st[N];vector<int> g[N],cut;
int tot=1,head[N];
struct node{int to,nxt,cw;}e[M<<1];
il void add(int u,int v,int w){e[++tot]={v,head[u],w},head[u]=tot;}
void pretar(int u,int f){
	dfn[u]=low[u]=++cur,fa[u]=f;
	go(i,u){
		int v=e[i].to;
		if(!dfn[v]){
			pd[i/2]=1,g[u].eb(v);
			pretar(v,i),low[u]=min(low[u],low[v]);
			if(low[v]>dfn[u])cut.eb(i/2);
		}else if(i!=(f^1))low[u]=min(low[u],dfn[v]),st[u].insert(dfn[v]);
	}
}
void dfs(int u,int f){
	low[u]=++cur;
	for(int v:g[u]){
		dfs(v,u),low[u]=min(low[u],low[v]);
		if(low[v]>dfn[u])cut.eb(fa[v]/2);
	}
	low[u]=min(low[u],*st[u].begin());
}
void tarjan(int u,int f){
	dfn[u]=low[u]=++cur,fa[u]=f;
	go(i,u){
		int v=e[i].to;
		if(e[i].cw==-1)continue;
		if(!dfn[v]){
			tarjan(v,i),low[u]=min(low[u],low[v]);
			if(low[v]>dfn[u])cut.eb(i/2);
		}else if(i!=(f^1))low[u]=min(low[u],dfn[v]);
	}
}
il void init(){mems(low,0),cur=0,cut.clear();}
void Yorushika(){
	scanf("%d%d%d%d",&n,&m,&s,&t);
	rep(i,1,m){
		int u,v,w;scanf("%d%d%d",&u,&v,&w);
		add(u,v,w),add(v,u,w);
	}
	pretar(s,0);
	if(!dfn[t])return puts("0\n0"),void();
	int u=t;
	while(u!=s){
		vis[fa[u]/2]=1;
		u=e[fa[u]^1].to;
	}
	int ans=(int)2e9+1,a=-1,b=-1;
	for(int i:cut)if(vis[i]&&e[i*2].cw<ans)ans=e[i*2].cw,a=i,b=0;
	for(int i=2;i<=tot;i+=2){
		int u=e[i].to,v=e[i^1].to;
		if(pd[i/2])continue;
		st[u].erase(st[u].find(dfn[v])),st[v].erase(st[v].find(dfn[u]));
		init(),dfs(s,0);
		for(int j:cut)if(vis[j]&&e[i].cw+e[j*2].cw<ans)ans=e[i].cw+e[j*2].cw,a=i/2,b=j;
		st[u].insert(dfn[v]),st[v].insert(dfn[u]);
	}
	for(int i=2;i<=tot;i+=2){
		int u=e[i].to,v=e[i^1].to;
		if(!pd[i/2])continue;
		int tmp=e[i].cw;
		e[i].cw=e[i^1].cw=-1;
		init(),mems(fa,0),mems(dfn,0);
		tarjan(s,0);
		mems(vis,0),e[i].cw=e[i^1].cw=tmp;
		if(!dfn[t])continue;
		int p=t;
		while(p!=s){
			vis[fa[p]/2]=1;
			p=e[fa[p]^1].to;
		}
		for(int j:cut)if(vis[j]&&e[i].cw+e[j*2].cw<ans)ans=e[i].cw+e[j*2].cw,a=i/2,b=j;
	}
	if(a==-1)puts("-1");
	else if(!b)printf("%d\n1\n%d\n",ans,a);
	else printf("%d\n2\n%d %d\n",ans,a,b);
}
signed main(){
	int t=1;
	//	scanf("%d",&t);
	while(t--)
		Yorushika();
}

标签:tarjan,cut,int,d%,dfn,low,CF700C
From: https://www.cnblogs.com/yinhee/p/18062352/CF700C

相关文章