UOJ496 新年的新航线

考虑多边形最外侧的三角形,可以发现与外侧的点相邻的两条边中必定恰好删除一条。

所以,我们把两条都删掉,然后在三角形内侧的边上打一个标记,表示要恢复一条边。

 接下来的处理三角形需要考虑标记,不妨设这个三角形为 $(u,w,v)$($w$ 为外侧点),分类讨论:

  1. $(u,w)$ 与 $(w,v)$ 都有标记:把标记点都连到 $w$,再把 $w$ 标记到 $(u,,v)$ 上,这样 $w$ 的度为3;
  2. $(u,w)$ 与 $(w,v)$ 中有一个有标记:设 $(u,w)$ 有标记,则把标记点和 $w$ 都连到 $u$ 上;
  3. 都没有标记:把 $w$ 标记到 $(u,v)$ 上。

最后删到剩4个点时暴力搜一下即可。

 复杂度 $O(n)$。

#include<cstdio>
#define For(i,A,B) for(i=(A);i<=(B);++i)
const int N=500050;
char rB[1<<21],*rS,*rT,wB[(1<<21)+50];
int wp=-1;
inline char gc(){return rS==rT&&(rT=(rS=rB)+fread(rB,1,1<<21,stdin),rS==rT)?EOF:*rS++;}
inline void flush(){fwrite(wB,1,wp+1,stdout);wp=-1;}
inline void pc(char c){if(wp>(1<<21))flush();wB[++wp]=c;}
inline int rd(){
    char c=gc();
    while(c<48||c>57)c=gc();
    int x=c&15;
    for(c=gc();c>=48&&c<=57;c=gc())x=(x<<3)+(x<<1)+(c&15);
    return x;
}
short buf[15];
inline void wt(int x){
    if(wp>(1<<21))flush();
    short l=-1;
    while(x>9){
        buf[++l]=x%10;
        x/=10;
    }
    wB[++wp]=x|48;
    while(l>=0)wB[++wp]=buf[l--]|48;
}
int G[N],to[N<<2],nex[N<<2],sz=0,d[N],lst[N],nxt[N],val[N],st[N],sl=-1,id[N],p[4],a[5],b[5],D[4];
bool del[N],used[5],chc[4];
inline void adde(int u,int v){
    to[++sz]=v;nex[sz]=G[u];G[u]=sz;
    to[++sz]=u;nex[sz]=G[v];G[v]=sz;
}
bool dfs2(int h){
    if(h==4)return D[0]!=2&&D[1]!=2&&D[2]!=2&&D[3]!=2;
    if(!val[p[h]])return dfs2(h+1);
    ++D[h];chc[h]=0;
    if(dfs2(h+1))return 1;
    --D[h];++D[h+1&3];chc[h]=1;
    if(dfs2(h+1))return 1;
    --D[h+1&3];
    return 0;
}
bool dfs1(int h,int m){
    if(!m)return dfs2(0);
    if(h==5)return 0;
    ++D[a[h]];++D[b[h]];used[h]=1;
    if(dfs1(h+1,m-1))return 1;
    --D[a[h]];--D[b[h]];used[h]=0;
    if(dfs1(h+1,m))return 1;
    return 0;
}
int main(){
    int n=rd(),i,j,u,v,w,cnt=0;
    if(n==3){
        puts("-1");
        return 0;
    }
    For(i,4,n){
        u=rd();v=rd();
        adde(u,v);
        ++d[u];++d[v];
    }
    For(i,1,n){
        adde(lst[i]=i==1?n:i-1,i);nxt[i]=i==n?1:i+1;
        if(!d[i])st[++sl]=i;
    }
    For(i,5,n){
        u=lst[w=st[sl--]];v=nxt[w];
        if(val[u])if(val[w]){
            wt(w);pc(' ');wt(val[u]);pc('\n');
            wt(w);pc(' ');wt(val[w]);pc('\n');
            val[u]=w;
        }else{
            wt(u);pc(' ');wt(w);pc('\n');
            wt(u);pc(' ');wt(val[u]);pc('\n');
            val[u]=0;
        }else if(val[w]){
            wt(v);pc(' ');wt(w);pc('\n');
            wt(v);pc(' ');wt(val[w]);pc('\n');
        }else val[u]=w;
        del[w]=1;
        lst[nxt[u]=v]=u;
        if(!--d[u])st[++sl]=u;
        if(!--d[v])st[++sl]=v;
    }
    For(i,1,n)if(!del[i])p[id[i]=cnt++]=i;
    cnt=0;
    For(i,0,3)
        for(j=G[p[i]];j;j=nex[j])if(!del[v=to[j]]&&i<id[v]){a[cnt]=i;b[cnt++]=id[v];}
    dfs1(0,3);
    For(i,0,4)if(used[i]){wt(p[a[i]]);pc(' ');wt(p[b[i]]);pc('\n');}
    For(i,0,3)if(val[p[i]]){
        wt(val[p[i]]);pc(' ');
        wt(chc[i]?p[i+1&3]:p[i]);
        pc('\n');
    }
    flush();
    return 0;
}
View Code

猜你喜欢

转载自www.cnblogs.com/sunshine-chen/p/12640715.html