ajmddzp

emmmm....学校的oj被查水表了,扒不到原题面,所以....

但是我还是扒到了题面。。。

 

 

题目大意:给定一个完全图,删掉其中一些边,然后求其字典序最小的遍历顺序

有点像去年day2T1啊....

但是数据范围如果建图的话就可以螺旋升天了。

很容易想到建反图(郑州集训233,可是这题不建反图会死)

然后想怎么遍历....

dfs序无疑,但是该怎么....跑这么多呢....

(真的很难想)

solution:

删边。

可以说删边。

既然要求字典序最小,那就给它一个字典序最小:123456789

把所有点先连上,向下跑,判断这两点之间的路有没有被炸掉,要是被炸掉了,就跑到i+2那个点去,然后把路删了,连到下面去。

有些坑人,代码细节不少。

#include<iostream>
#include<cstdio>
#include<vector>
#include<algorithm>
#define rg register
using namespace std;
inline int read()//怕被卡加的读优
{
    int x=0,f=1;char s=getchar();
    while(s>\'9\'||s<\'0\'){if(s==\'-\')f=-1;s=getchar();}
    while(s<=\'9\'&&s>=\'0\'){x=x*10+s-\'0\';s=getchar();}
    return x*f;
}
const int maxn=100005;
int n,m;
vector < int > g[maxn];//无权图用vector存方便
int nxt[maxn];//学校oj卡关键字太狠了
int to[maxn];//辅助删边数组
void dfs(int u)
{
    printf("%d\n",u);//走一个输出一个
    sort(g[u].begin(),g[u].end());//对炸掉的点排序,方便下面二分查找
    nxt[to[u]]=nxt[u];//删边
    to[nxt[u]]=to[u];
    for(rg int i=nxt[0];i<=n;i=nxt[i])
    {
        if(i!=g[u][lower_bound(g[u].begin(),g[u].end(),i)-g[u].begin()])//找不找得到一个被炸的点与自己相同
        {
            dfs(i);//向下搜
            return;//老子不搜了
        }
    }
}
  
int main()
{
    n=read();m=read();
    for(rg int i=1;i<=n;i++)
    {
        nxt[i]=i+1;//连一个字典序最小数组
        to[i]=i-1;//辅助
        g[i].push_back(2147483647);//注意了,如果一个vector里是空的的话,那么sort啊,lower_bound会出事,所以放进去一个无限大
    }
    nxt[0]=1; to[1]=0;
    for(rg int i=1;i<=m;i++)
    {
        int x,y;
        x=read();y=read();//scanf("%d%d",&x,&y);
        g[x].push_back(y);
        g[y].push_back(x);//建反图
    }
    dfs(1);//字典序最小,肯定是从1开头最小
    return 0;
}

 

分类:

技术点:

相关文章:

  • 2021-09-30
  • 2022-01-29
  • 2021-12-05
  • 2022-12-23
  • 2022-02-20
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
猜你喜欢
  • 2021-09-23
  • 2022-12-23
  • 2021-03-31
  • 2022-01-04
  • 2021-07-13
  • 2021-10-17
  • 2021-08-25
相关资源
相似解决方案