• Goodbye Wuxu.B.新年的Dog划分(交互 二分 二分图)


    题目链接


    官方题解写得很详细,我竟然看懂了

    Subtask1:
    暴力的话,猜可以(2^n)枚举点集(A,B),将除了(A,B)之间的边全部删掉,然后询问。一定有至少一组(A,B)返回连通。
    设二分图两边的点集分别是(S,T),能猜到此时(S=A,T=B)。假设(Scap A eqemptyset)(Tcap A eqemptyset),那(A,B)连通说明(S,T)通过同一个点连通,显然不会,因此(Tcap A=emptyset)。同理(Scap B eqemptyset)。所以有(S=A,T=B)。询问次数(O(2^n))

    Subtask2:
    如果图是二分图,考虑找到原图的一棵生成树,然后就可以黑白染色找出(S)了。
    尝试依次删掉图中所有边。如果删掉一条边时由连通变为不连通,说明它在生成树上,保留这条边,否则删掉这条边。最终一定剩下(n-1)条边,就是原图的生成树。
    询问次数(O(frac{n(n-1)}{2}))

    Subtask3:
    找生成树时一条一条枚举边太慢了,可以二分。如果删掉(1sim mid)中的边图仍连通,就删掉,否则找到那条必须边保留。
    这样的事件会进行(n-1)次,每次需要二分(logfrac{n(n-1)}{2}approx2log n)次。
    黑白染色后得到(S,T),只靠生成树是可以连接(S,T)的。如果图不是二分图,那么把(S,T)之间的非树边全删掉,一定存在某一条树边,使得删掉这条树边后图仍连通。
    总询问次数(2(n-1)log n+n-1)

    Subtask4:
    考虑对点二分,把二分时(2)的常数去掉。
    枚举每个点,二分它与哪个点之间的边必须保留即可。
    询问次数(nlog n)


    //4955ms	1584kb
    #include <cstdio>
    #include <cctype>
    #include <vector>
    #include <cstring>
    #include <algorithm>
    #define pb push_back
    #define fir first
    #define sec second
    #define mp std::make_pair
    #define pr std::pair<int,int>
    
    #include "graph.h"
    
    const int N=233;
    
    int Enum,H[N],nxt[N<<1],to[N<<1],col[N];
    bool tag[N][N];
    std::vector<pr> tr;
    
    inline void AE(int u,int v)
    {
    	to[++Enum]=v, nxt[Enum]=H[u], H[u]=Enum;
    	to[++Enum]=u, nxt[Enum]=H[v], H[v]=Enum;
    }
    void DFS(int x)
    {
    	for(int i=H[x],v; i; i=nxt[i])
    		if(!col[v=to[i]]) tag[x][v]=tag[v][x]=1, tr.push_back(mp(x,v)), col[v]=col[x]^1, DFS(v);
    }
    std::vector<int> check_bipartite(int n)
    {
    	std::vector<pr> q;
    	for(int x=0; x+1<n; ++x)
    	{
    		int now=x+1;
    		while(now<n)
    		{
    			for(int i=now; i<n; ++i) q.push_back(mp(x,i));
    			if(query(q)) break;
    			for(int i=now; i<n; ++i) q.pop_back();
    			int l=now,r=n-1,mid;
    			while(l<r)
    			{
    				int mid=l+r>>1;
    				for(int i=l; i<=mid; ++i) q.push_back(mp(x,i));
    				if(query(q)) l=mid+1;
    				else r=mid;
    				for(int i=l; i<=mid; ++i) q.pop_back();
    			}
    			AE(x,l), now=l+1;
    		}
    	}
    	col[0]=2, DFS(0);
    	std::vector<int> ans; q.clear();
    	for(int i=0; i<n; ++i)//Check if it's a Bipartite Graph
    		for(int j=i+1; j<n; ++j)
    			if(col[i]!=col[j] && !tag[i][j]) q.push_back(mp(i,j));
    	for(int i=0,l=tr.size(); i<l; ++i)
    	{
    		q.push_back(tr[i]);
    		if(query(q)) return ans;
    		q.pop_back();
    	}
    	for(int i=0; i<n; ++i) if(col[i]==2) ans.push_back(i);
    	return ans;
    }
    

    67分代码:

    #include <cstdio>
    #include <cctype>
    #include <vector>
    #include <algorithm>
    #define pb push_back
    #define fir first
    #define sec second
    #define mp std::make_pair
    #define pr std::pair<int,int>
    
    #include "graph.h"
    
    const int N=233,M=N*N/2;
    
    int Enum,H[N],nxt[N<<1],to[N<<1],col[N];
    pr e[M];
    bool tag[M];
    
    inline void AE(int u,int v)
    {
    	to[++Enum]=v, nxt[Enum]=H[u], H[u]=Enum;
    	to[++Enum]=u, nxt[Enum]=H[v], H[v]=Enum;
    }
    void DFS(int x)
    {
    	for(int i=H[x],v; i; i=nxt[i])
    		if(!col[v=to[i]]) col[v]=3-col[x], DFS(v);
    }
    std::vector<int> check_bipartite(int n)//2(n-1)logn+n-1
    {
    	int m=0;
    	for(int i=0; i<n; ++i)
    		for(int j=i+1; j<n; ++j) e[++m]=mp(i,j);
    	for(int T=n-1,now=1; T--; )
    	{
    		int l=now,r=m,mid;
    		while(l<r)
    		{
    			int mid=l+r>>1;
    			std::vector<pr> q;
    			for(int i=1; i<=mid; ++i) if(!tag[i]) q.push_back(e[i]);
    			if(query(q)) l=mid+1;
    			else r=mid;
    		}
    		AE(e[r].fir,e[r].sec), tag[r]=1, now=r+1;
    	}
    	std::vector<int> ans;
    	col[0]=1, DFS(0);
    	for(int i=1; i<=m; ++i)//Check if it's a Bipartite Graph
    		if(tag[i])
    		{
    			std::vector<pr> q; q.push_back(e[i]);
    			for(int j=1; j<=m; ++j)
    				if(!tag[j] && col[e[j].fir]!=col[e[j].sec]) q.push_back(e[j]);
    			if(query(q)) return ans;
    		}
    	for(int i=0; i<n; ++i) if(col[i]==1) ans.push_back(i);
    	return ans;
    }
    
  • 相关阅读:
    关于 转换图片url为base64格式以及base64格式图片地址转为图片文件
    rem布局在Androidwebview中页面错乱
    vue中 $event 的用法--获取当前父元素,子元素,兄弟元素
    vue实现动态改变title
    vue页面跳转-携带参数
    vue项目打包部署生产环境
    Mark区
    kma 2019CSP前刷题记录
    机房的沙茶日常
    2019NOIP算法复健+学习
  • 原文地址:https://www.cnblogs.com/SovietPower/p/10404783.html
Copyright © 2020-2023  润新知