zoukankan      html  css  js  c++  java
  • UOJ496 新年的新航线

    Link
    如果(n e3)那么一定有解。
    我们考虑这样一种构造方式:每次找到((a,b,c))三个点,选((a,b),(a,c))这两条边,然后把(b,c)两个点删掉。
    很显然这样构造出来的生成树一定是合法的。
    那么我们递归地构造,每次按上面所说选两条边并删两个点,并且为了方便需要保证删完点之后依旧是一个多边形。
    对于一个点(x),我们求出它后面的(4)个点(a,b,c,d)
    因为我们保证任意时刻删完点后它是一个多边形,因此((x,a),(a,b),(b,c),(c,d))都一定存在。
    因为我们需要保证删完点后它还是一个多边形,因此(x,d)这两个点是不能删的。
    那么我们就只需要考虑删掉((a,b,c))中的两个的三种情况了。
    如果((x,b),(b,d))存在我们就把((a,b),(b,c))选上,然后把(a,c)删掉。
    如果((x,c),(x,b))存在我们就把((x,a),(x,b))选上,然后把(a,b)删掉。
    如果((x,c),(a,c))存在我们就把((a,c),(b,c))选上,然后把(a,b)删掉。
    可以发现这么操作一定是满足我们上面所说的所有要求的。
    如果成功删了的话我们递归处理,把(x)移到(x)的前一个点。
    如果没能删的话我们把(x)移到(x)的下一个点。
    当剩余点数不超过(5)时我们一定可以找到一个点,它跟其它的点都有连边,那么我们以这个点为根其它的点作为叶子节点即可构造一个合法的生成树。
    维护前后的点用链表就可以了。

    #include<cstdio>
    #include<cctype>
    #include<unordered_map>
    namespace IO
    {
        char ibuf[(1<<21)+1],obuf[(1<<21)+1],st[15],*iS,*iT,*oS=obuf,*oT=obuf+(1<<21);
        char Get(){return (iS==iT? (iT=(iS=ibuf)+fread(ibuf,1,(1<<21)+1,stdin),(iS==iT? EOF:*iS++)):*iS++);}
        void Flush(){fwrite(obuf,1,oS-obuf,stdout),oS=obuf;}
        void Put(int x){*oS++=x;if(oS==oT)Flush();}
        int read(){int x=0,c=Get();while(!isdigit(c))c=Get();while(isdigit(c))x=x*10+c-48,c=Get();return x;}
        void write(int x,int c){int top=0;if(!x)Put('0');while(x)st[++top]=(x%10)+48,x/=10;while(top)Put(st[top--]);Put(c);}
    }
    using IO::read;
    using IO::write;
    const int N=500007;
    int k,c,a[100],L[N],R[N];
    std::unordered_map<int,int>e[N];
    void del(int x){R[L[x]]=R[x],L[R[x]]=L[x];}
    void out(int u,int v){write(u,' '),write(v,'
    ');}
    void dfs(int x)
    {
        if(k<=5)
        {
    	a[c=1]=x;
    	for(int i=R[x];i^x;i=R[i]) a[++c]=i;
    	for(int i=1,j;i<=k;++i)
    	{
    	    for(j=1;j<=k;++j) if(i^j&&!e[a[i]][a[j]]) break;
    	    if(j>k){for(j=1;j<=k;++j) if(i^j) out(a[i],a[j]);return ;}
    	}
        }
        for(int i=x;;i=R[i])
        {
    	int a=R[i],b=R[a],c=R[b],d=R[c];
    	if(e[i][c])
    	{
    	    if(e[i][b]) return del(a),del(b),k-=2,dfs(L[i]),out(i,a),out(i,b);
    	    if(e[a][c]) return del(a),del(b),k-=2,dfs(L[i]),out(a,c),out(b,c);
    	}
    	if(e[i][b]&&e[b][d]) return del(a),del(c),k-=2,dfs(L[i]),out(a,b),out(c,b);
        }
    }
    int main()
    {
        int n=read();
        if(n==3) return !printf("-1");
        for(int i=1,u,v;i<=n-3;++i) u=read(),v=read(),e[u][v]=e[v][u]=1;
        for(int i=1;i<=n;++i) L[i]=i-1,R[i]=i%n+1,e[i][i%n+1]=e[i%n+1][i]=1;
        L[1]=n,k=n,dfs(1),IO::Flush();
    }
    
  • 相关阅读:
    利用Oracle分析函数row_number和sys_connect_by_path实现多行数据合并为一行
    public string err属性
    table冻结表头和列[转]
    转:Js日期操作
    ASP.NET中JSON的序列化和反序列化
    javascript Date format(js日期格式化) [转]
    刚开通的博客
    调用图片
    散记兼容,需要整理
    ie6、div高度低于字体大小、则继承fontsize
  • 原文地址:https://www.cnblogs.com/cjoierShiina-Mashiro/p/12293158.html
Copyright © 2011-2022 走看看