zoukankan      html  css  js  c++  java
  • 4.18 省选模拟赛 桥 边双联通分量 长链剖分维护贪心

    avatar
    avatar

    只存在加边操作 所以每次只对割边有影响。

    考虑求出所有的边双联通分量 然后进行缩点。

    那么原图就变成了一颗树 且所有边都是割边。

    考虑k==1的时候 显然是求出树的直径。

    考虑k>1时 一个错误的贪心:把刚才树的直径上的边标记为0 然后再求直径......

    容易构造出反例让其错误。

    题解上的做法过于神仙 看不懂。

    给一种自己做CF某道题后得到的贪心思路。

    容易发现选出k条边 某种意义上来说是选出了2k个点。

    我们还可以知道这2k个点中 其中必然有两个点包含树的直径两端点。

    但是直接选出2k个点可能是不合法的。而且此时无根很难计算出来答案。

    我们知道了必然有两个点是树的直径两端点了 以其中一个点为根。

    那么剩下的就是选取2k-1个点每个点的最初权值为点到根路径上的边数。

    考虑每次选取最大的。这个贪心容易使用长链剖分进行优化 排一下序或者使用堆维护即可。

    正确性:最初根为直径某个端点显然正确,接着这2k个点包括根显然是可以两两配对组成k条边和题目吻合。

    最优性:每次权值都尽可能的大所以是最优的。(还需要斟酌一下 好多题都是这样贪的

    const int MAXN=200010;
    int n,m,Q,id,len=1,cnt,cc,len1=1,s1,s2,maxx;
    int c[MAXN],vis[MAXN],dis[MAXN];
    int dfn[MAXN],low[MAXN],mark[MAXN<<1],f[MAXN],q[MAXN],mx[MAXN];
    int lin[MAXN],ver[MAXN<<1],nex[MAXN<<1],sz[MAXN],son[MAXN],fa1[MAXN];
    int lin1[MAXN],ver1[MAXN<<1],nex1[MAXN<<1],e1[MAXN<<1];
    inline void add(int x,int y)
    {
    	ver[++len]=y;
    	nex[len]=lin[x];
    	lin[x]=len;
    }
    inline void add1(int x,int y,int z)
    {
    	ver1[++len1]=y;
    	nex1[len1]=lin1[x];
    	lin1[x]=len1;
    	e1[len1]=z;
    }
    inline void dfs(int x,int las)
    {
    	dfn[x]=low[x]=++cnt;
    	go(x)
    	{
    		if(i==(las^1))continue;
    		if(!dfn[tn])
    		{
    			dfs(tn,i);
    			low[x]=min(low[x],low[tn]);
    			if(low[tn]>dfn[x])mark[i]=1;
    		}
    		else low[x]=min(low[x],dfn[tn]);
    	}
    }
    inline void dfs(int x)
    {
    	vis[x]=1;c[x]=id;
    	go(x)
    	{
    		if(vis[tn]||mark[i]||mark[i^1])continue;
    		dfs(tn);
    	}
    }
    inline int bfs(int w)
    {
    	maxx=0;++cc;
    	int l=0,r=0,ww=0;
    	q[++r]=w;dis[w]=0;vis[w]=cc;
    	while(++l<=r)
    	{
    		int x=q[l];
    		if(dis[x]>maxx)
    		{
    			ww=x;
    			maxx=dis[x];
    		}
    		for(int i=lin1[x];i;i=nex1[i])
    		{
    			int tn=ver1[i];
    			if(vis[tn]!=cc)
    			{
    				dis[tn]=dis[x]+e1[i];
    				vis[tn]=cc;
    				q[++r]=tn;
    			}
    		}
    	}
    	return ww;
    }
    inline int dp(int x,int fa)
    {
    	if(x==s2)return 1;
    	for(int i=lin1[x];i;i=nex1[i])
    	{
    		int tn=ver1[i];
    		if(tn==fa)continue;
    		if(dp(tn,x))
    		{
    			e1[i]=e1[i^1]=0;
    			return 1;
    		}
    	}
    	return 0;
    }
    inline int getfather(int x){return x==f[x]?x:f[x]=getfather(f[x]);}
    inline void dp1(int x,int fa)
    {
    	sz[x]=sz[fa]+1;mx[x]=sz[x];
    	fa1[x]=fa;
    	for(int i=lin1[x];i;i=nex1[i])
    	{
    		int tn=ver1[i];
    		if(tn==fa)continue;
    		dp1(tn,x);
    		//cout<<mx[tn]<<' '<<mx[x]<<endl;
    		if(mx[tn]>mx[x])
    		{
    			son[x]=tn;
    			mx[x]=mx[tn];
    		}
    	//	cout<<son[x]<<endl;
    	}
    }
    priority_queue<int>s;
    inline void dp2(int x,int fa)
    {
    	if(fa==x)
    	{
    		if(x==s1)s.push(mx[x]-sz[x]);
    		else s.push(mx[x]-sz[fa1[x]]);
    		//cout<<mx[x]-sz[x]<<endl;
    		//cout<<son[x]<<' '<<x<<endl;
    	}
    	if(son[x])dp2(son[x],fa);
    	for(int i=lin1[x];i;i=nex1[i])
    	{
    		int tn=ver1[i];
    		if(tn==fa1[x]||son[x]==tn)continue;
    		dp2(tn,tn);
    		//cout<<"ww"<<endl;
    	}
    }
    int main()
    {
    	//freopen("1.in","r",stdin);
    	freopen("bridge.in","r",stdin);
    	freopen("bridge.out","w",stdout);
    	get(n);get(m);get(Q);
    	rep(1,m,i)
    	{
    		int get(x);int get(y);
    		add(x,y);add(y,x);
    	}
    	dfs(1,0);cc=1;
    	rep(1,n,i)if(!vis[i])++id,dfs(i);
    	rep(1,id,i)f[i]=i;
    	rep(1,n,j)go(j)
    	{
    		if(c[j]==c[tn])continue;
    		int xx=getfather(c[j]);
    		int yy=getfather(c[tn]);
    		if(xx==yy)continue;
    		f[xx]=yy;
    		add1(c[j],c[tn],1);
    		add1(c[tn],c[j],1);
    	}
    	--id;int ans=0;
    	s1=bfs(1);s2=bfs(s1);
    	dp1(s1,0);
    	dp2(s1,s1);
    	ans+=s.top();
    	s.pop();
    	put(ans);
    	rep(2,Q,i)
    	{
    		if(s.size())
    		{
    			ans+=s.top();
    			s.pop();
    		} 
    		if(s.size())
    		{
    			ans+=s.top();
    			s.pop();
    		} 
    		put(ans);
    	}
    	return 0;
    }
    
  • 相关阅读:
    Apache Spark 2.2.0 中文文档
    Apache Spark 2.2.0 中文文档
    Apache Spark 2.2.0 中文文档
    Apache Spark 2.2.0 中文文档
    Apache Spark 2.2.0 中文文档
    Apache Spark RDD(Resilient Distributed Datasets)论文
    Apache Spark 2.2.0 中文文档
    Apache Spark 2.2.0 中文文档
    【机器学习实战】第10章 K-Means(K-均值)聚类算法
    [译]flexbox全揭秘
  • 原文地址:https://www.cnblogs.com/chdy/p/12770030.html
Copyright © 2011-2022 走看看