• 【考试总结】20220404


    构树

    给定的边是一定存在的,先连上

    剩下的枚举不在联通块的两个点是不是能连边,能就连

    如果出环或者到最后都不能联通就是无解

    Code Display
    const int N=1010;
    int n,l[N],r[N];
    vector<pair<int,int> >edge;
    struct DSU{
        int fa[N];
        inline void init(int n){rep(i,1,n) fa[i]=i; return ;}
        inline int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
        inline void merge(int x,int y){fa[find(x)]=find(y); return ;}
    }Dsu;
    map<int,int> mp[N];
    inline void ins(int x,int y){
        mp[x][y]=1;
        mp[y][x]=1;
        edge.emplace_back(x,y);
        Dsu.merge(x,y);
    }
    signed main(){
        freopen("tree.in","r",stdin); freopen("tree.out","w",stdout);
        n=read(); Dsu.init(n);
        rep(i,1,n){
            l[i]=read(),r[i]=read();
            if(!mp[i].count(l[i])){
                if(Dsu.find(l[i])==Dsu.find(i)) puts("-1"),exit(0);
                ins(i,l[i]);
            }
            if(!mp[i].count(r[i])){
                if(Dsu.find(r[i])==Dsu.find(i)) puts("-1"),exit(0);
                ins(i,r[i]);
            }
        }
        for(int i=1;i<=n;++i){
            for(int j=l[i]+1;j<r[i];++j) if(!mp[i].count(j)){
                if(Dsu.find(i)==Dsu.find(j)) continue;
                if(l[j]<=i&&i<=r[j]) ins(i,j);
            }
        }
        if(edge.size()<n-1) puts("-1"),exit(0);
        for(auto e:edge) print(e.fir),print(e.sec),putchar('\n');
        return 0;
    }
    

    交互

    \(\text{key observation}\)\(1\) 号节点没有左儿子,那么可以从 \(1\) 开始不断迭代:

    • 如果当前节点没有右子树,那么这个子树被确定,此时已知结构区间 \(1,i\) 的根的父亲是 \(i+1\) ,继续迭代

    • 如果当前节点有右子树,右子树左端点确定,是一个子问题,递归求子树进行迭代

    打字的时候 交 点出了 JOI ,不知道这是不是清明节的冥冥之中

    Code Display
    #include "interact.h"
    using namespace std;
    int n;
    inline int solve(int L,int rt,int &R){
    	R=rt;
    	if(query(rt,L,R)) return rt;
    	for(int lst=0,nxt;;lst=nxt){
    		nxt=solve(rt+1,R+1,R);
    		if(lst) report(lst,nxt);
    		if(query(rt,L,R)) return report(rt,nxt),rt;
    	}
    }
    void guess(int N){
    	n=N;
    	int nxt,r=0;
    	for(int lst=0;r<n;lst=nxt){
    		nxt=solve(1,r+1,r);
    		if(lst) report(lst,nxt);
    	}
    	return ;
    }
    

    构图

    枚举有多少点的度数是 \(k\) ,由于不能相邻,所以每次找到当前其它点中度数最小的点连边即可

    对于度数超过 \(k\) 的点中完成连边且度数仍然不够的就自行连边即可,由于 \(n\le 1000\) 所以可以通过

    Code Display
    int n,k;
    vector<pair<int,int> >ans,edge;
    inline void solve(int lef){
        edge.clear();
        deque<int> q;
        vector<int> deg(n+1);
        for(int i=lef+1;i<=n;++i) q.push_back(i);
        rep(i,1,lef){
            int tmp=k;
            while(tmp--){
                int x=q.front(); q.pop_front();
                deg[x]++;
                q.push_back(x);
                edge.emplace_back(x,i);
            }
        }
        vector<int> nds;
        while(q.size()){
            int x=q.front(); q.pop_front();
            if(deg[x]+q.size()<=k) return ;
            while(deg[x]<=k){
                int y=q.front(); q.pop_front();
                deg[x]++; deg[y]++;
                edge.emplace_back(x,y);
                q.push_back(y);
            }
        }
        if(ans.empty()||ans.size()>edge.size()) swap(ans,edge);
    }
    signed main(){
    	freopen("graph.in","r",stdin); freopen("graph.out","w",stdout);
    	n=read(); k=read();	
    	for(int i=1;i<=n-k;++i) solve(i);
    	if(ans.empty()) puts("Impossible"),exit(0);
        cout<<ans.size()<<endl;
        for(auto t:ans) printf("%lld %lld\n",t.fir,t.sec);
        return 0;
    }
    

  • 相关阅读:
    mfc中的_T
    zmq的send
    c++内存相关函数
    如何运行linux shell程序
    Dockfile中的命令如何在.sh中执行
    Linux 错误: $' ': command not found
    实战ZeroMQ的PUSH/PULL推拉模式
    Servlet笔记
    进程控制块(PCB)
    Makefile规则介绍
  • 原文地址:https://www.cnblogs.com/yspm/p/16099395.html
Copyright © 2020-2023  润新知