zoukankan      html  css  js  c++  java
  • 【BZOJ4331】[JSOI2012]越狱老虎桥(Tarjan)

    【BZOJ4331】[JSOI2012]越狱老虎桥(Tarjan)

    题面

    BZOJ
    然而BZOJ是权限题QwQ
    洛谷

    题解

    先求出所有割边,那么显然要割掉一条割边。
    如果要加入一条边,那么显然是把若干条割边串起来,使得这些割边不能被割掉。
    那么把割边求出来之后,按照权值从小到大考虑所有割边,第一个不能和前面的构成一条链的割边就是答案。
    那么考虑能否构成一条链。
    首先缩点后形成一棵树,然后维护链的开头、链的结尾,以及链上深度最浅的位置,然后大力讨论一波就好了。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define MAX 500500
    #define ll long long
    inline int read()
    {
    	int x=0;bool t=false;char ch=getchar();
    	while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    	if(ch=='-')t=true,ch=getchar();
    	while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
    	return t?-x:x;
    }
    struct Line{int v,next;}e[MAX<<2];
    int h[MAX],cnt=2,U[MAX<<1],V[MAX<<1],w[MAX<<1];
    inline void Add(int u,int v){e[cnt]=(Line){v,h[u]};h[u]=cnt++;}
    int dfn[MAX],low[MAX],tim;bool ins[MAX],cut[MAX<<1];
    int S[MAX],top,G[MAX],gr;
    void Tarjan(int u,int ff)
    {
    	dfn[u]=low[u]=++tim;S[++top]=u;
    	for(int i=h[u];i;i=e[i].next)
    	{
    		int v=e[i].v;if(v==ff)continue;
    		if(!dfn[v])
    		{
    			Tarjan(v,u);
    			low[u]=min(low[u],low[v]);
    		}
    		else low[u]=min(low[u],dfn[v]);
    		if(low[v]>dfn[u])cut[i>>1]=true;
    	}
    	if(dfn[u]==low[u])
    	{
    		++gr;int v;
    		do{v=S[top--];G[v]=gr;}while(u!=v);
    	}
    }
    int fa[MAX],dep[MAX],tp[MAX],hson[MAX],size[MAX];
    void dfs1(int u,int ff)
    {
    	fa[u]=ff;dep[u]=dep[ff]+1;size[u]=1;
    	for(int i=h[u];i;i=e[i].next)
    	{
    		int v=e[i].v;if(v==ff)continue;
    		dfs1(v,u);size[u]+=size[v];
    		if(size[v]>size[hson[u]])hson[u]=v;
    	}
    }
    void dfs2(int u,int t)
    {
    	tp[u]=t;if(hson[u])dfs2(hson[u],t);
    	for(int i=h[u];i;i=e[i].next)
    		if(e[i].v!=fa[u]&&e[i].v!=hson[u])
    			dfs2(e[i].v,e[i].v);
    }
    int LCA(int u,int v)
    {
    	while(tp[u]^tp[v])dep[tp[u]]<dep[tp[v]]?v=fa[tp[v]]:u=fa[tp[u]];
    	return dep[u]<dep[v]?u:v;
    }
    int n,m,p[MAX],tot;
    bool cmp(int a,int b){return w[a]<w[b];}
    int main()
    {
    	n=read();m=read();
    	for(int i=1;i<=m;++i)
    		U[i]=read(),V[i]=read(),w[i]=read(),Add(U[i],V[i]),Add(V[i],U[i]);
    	Tarjan(1,0);
    	for(int i=2;i<cnt;i+=2)if(cut[i>>1])p[++tot]=i>>1;
    	sort(&p[1],&p[tot+1],cmp);
    	memset(h,0,sizeof(h));cnt=1;
    	for(int i=1;i<=m;++i)U[i]=G[U[i]],V[i]=G[V[i]];
    	for(int i=1;i<=m;++i)if(U[i]!=V[i])Add(U[i],V[i]),Add(V[i],U[i]);
    	dfs1(1,0);dfs2(1,1);
    	int H=U[p[1]],T=V[p[1]],M=0;
    	if(dep[H]<dep[T])swap(H,T);
    	for(int i=2;i<=tot;++i)
    	{
    		int u=U[p[i]],v=V[p[i]];if(dep[u]<dep[v])swap(u,v);
    		int a=LCA(u,H),b=LCA(v,H),c=LCA(u,T),d=LCA(v,T);
    		if(!M)
    		{
    			if(a==u&&b==v&&c==T&&d==T)continue;
    			if(a==H&&b==H){H=u;continue;}
    			if(c==u&&d==v){T=v;continue;}
    			if(c==d&&dep[c]<=dep[T]){T=u;M=v;continue;}
    			printf("%d
    ",w[p[i]]);return 0;
    		}
    		else
    		{
    			if(a==H&&b==H){H=u;continue;}
    			if(c==T&&d==T){T=u;continue;}
    			if(a==u&&b==v&&c==M&&d==M)continue;
    			if(a==M&&b==M&&c==u&&d==v)continue;
    			printf("%d
    ",w[p[i]]);return 0;
    		}
    	}
    	puts("-1");
    	return 0;
    }
    
  • 相关阅读:
    蛙蛙推荐:JS里声明事件处理的几种方式
    蛙蛙推荐:asp错误处理
    蛙蛙推荐:偶心目中的编程高手,大家也推荐一下
    access能否用vbs来写存储过程,是否支持参数名称 【星期一 2005年7月4日】
    MySQL索引相关
    ubuntu 禁用触摸板
    ubuntuFQ(转)
    bash编程笔记
    Hive环境搭建与入门(转)
    Linux SSH远程文件/目录传输命令scp
  • 原文地址:https://www.cnblogs.com/cjyyb/p/10458477.html
Copyright © 2011-2022 走看看