• bzoj 1515 [POI2006]Lis-The Postman 有向图欧拉回路


    LINK:Lis-The Postman

    看完题觉得 虽然容易发现是有向图欧拉回路 但是觉得很难解决这个问题。

    先分析一下有向图的欧拉回路:充要条件 图中每个点的入度-出度=0且整张图是一个强连通分量。

    证明:首先考虑前者 这个思想是 从一个点出去必然还能回来所以可以形成回路 后者保证了图是联通的。

    但是注意观察题目中有一些比较好的条件 每两个点之间的边最多有两条且方向不同。

    题目给了k条必须要要连续走的路径 容易想到多条路径可以合并在一起。

    这个操作看起来难做 但是 把边进行标号 然后只需要前驱和后继进行合并即可。

    判定条件:1 图中原本的点入度-出度=0.2 一条边在一条路径出现两次就是错的 3 一条边有多个前驱后继就是错的。

    这样 我们可以把一些边给合并起来了。我们可以要求一走走完这些边。

    4 这些边合并在一起后 存在环了那么肯定也走不了。

    剩下的就是一个正常的图了 跑欧拉回路即可。

    5 在新建的图中再次判断点的出度和入度。

    6 最后需要判断图联通与否。

    7 判断是否可以从1出发

    8 虽然没要求输出方案但是这里点一下 倒序输出点 点和点相连就是边了 更快的方法 输出点的时候可以直接记录将这个点送进来的边是哪个直接输出边。

    //#include<bitsstdc++.h>
    #include<iostream>
    #include<iomanip>
    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<ctime>
    #include<cmath>
    #include<cctype>
    #include<cstdlib>
    #include<queue>
    #include<deque>
    #include<stack>
    #include<vector>
    #include<algorithm>
    #include<utility>
    #include<bitset>
    #include<set>
    #include<map>
    #define ll long long
    #define db double
    #define INF 1000000000000000ll
    #define ldb long double
    #define pb push_back
    #define put_(x) printf("%d ",x);
    #define get(x) x=read()
    #define gt(x) scanf("%d",&x)
    #define gi(x) scanf("%lf",&x)
    #define put(x) printf("%d
    ",x)
    #define putl(x) printf("%lld
    ",x)
    #define gc(a) scanf("%s",a+1)
    #define rep(p,n,i) for(RE int i=p;i<=n;++i)
    #define go(x) for(int i=lin[x],tn=ver[i];i;tn=ver[i=nex[i]])
    #define fep(n,p,i) for(RE int i=n;i>=p;--i)
    #define pii pair<int,int>
    #define mk make_pair
    #define RE register
    #define P 1000000007
    #define S second 
    #define F first
    #define gf(x) scanf("%lf",&x)
    #define pf(x) ((x)*(x))
    #define ull unsigned long long
    #define ui unsigned
    #define EPS 1e-8
    #define mod 1000000007
    #define sq sqrt
    #define l(p) t[p].l
    #define r(p) t[p].r
    #define op(p) t[p].op
    #define cnt(p) t[p].cnt
    #define sum(p) t[p].sum
    #define zz p<<1
    #define yy p<<1|1
    using namespace std;
    char buf[1<<15],*fs,*ft;
    inline char getc()
    {
        return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;
    }
    inline int read()
    {
        RE int x=0,f=1;RE char ch=getc();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getc();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getc();}
        return x*f;
    }
    const int MAXN=200010,maxn=50010;
    int n,m,len,k,top;
    int du[MAXN],w[MAXN],b[MAXN],s[MAXN];
    map<int,int>H[maxn];
    struct wy{int x,y;}t[MAXN];
    int pre[MAXN],ne[MAXN],vis[MAXN];
    int lin[MAXN],ver[MAXN],nex[MAXN],fir[MAXN];
    inline void add(int x,int y,int w1)
    {
        ver[++len]=y;
        nex[len]=lin[x];
        lin[x]=len;
        ++du[x];--du[y];
        fir[len]=w1;
        //cout<<x<<' '<<y<<endl;
    }
    inline void js(){puts("NIE");exit(0);}
    inline void dfs(int x,int fa)
    {
        for(int &i=lin[x];i;i=nex[i])
        {
            if(vis[i])continue;
            vis[i]=1;
            dfs(ver[i],i);
        }
        s[++top]=fa;
        //put(x);
    }
    int main()
    {
        //freopen("1.in","r",stdin);
        //freopen("1.out","w",stdout);
        get(n);get(m);
        rep(1,m,i)
        {
            int get(x),get(y);
            t[i]=(wy){x,y};
            ++du[x];--du[y];
            H[x][y]=i;
        }
        rep(1,n,i)if(du[i])js();
        get(k);
        rep(1,k,i)
        {
            int get(x);
            int get(las);
            rep(1,x-1,j)
            {
                int get(y);
                if(H[las].find(y)==H[las].end())js();
                b[j]=H[las][y];
                if(w[b[j]]==i)js();
                las=y;
            }
            rep(1,x-2,j)
            {
                if(!pre[b[j+1]])pre[b[j+1]]=b[j];
                else if(pre[b[j+1]]!=b[j])js();
                if(!ne[b[j]])ne[b[j]]=b[j+1];
                else if(ne[b[j]]!=b[j+1])js();
            }
        }
        int cnt=0;
        rep(1,m,i)
            if(!pre[i])
            {
                int j;++cnt;
                for(j=i;ne[j];j=ne[j])++cnt;
                add(t[i].x,t[j].y,i);
            }
        if(cnt<m||!lin[1])js();
        rep(1,n,i)if(du[i])js();
        dfs(1,0);--top;
        rep(1,n,i)if(lin[i])js();
        puts("TAK");
        /*put(t[fir[s[top]]].x);
        fep(top,1,i)
        {
            int j=fir[s[i]];
            //put(t[j].x);
            do
            {
                put(t[j].y);
                j=ne[j];
            }while(j);
        }*/
        return 0;
    }
    
  • 相关阅读:
    NOIP2002字串变换[BFS]
    NOIP2000单词接龙[DFS]
    NOIP2003传染病控制[按层DFS]
    NOIP1999邮票面值设计[搜索|DP]
    USACO1.1Broken Necklace[环状DP作死]
    洛谷P1120小木棍[DFS]
    NOIP2000进制转换
    Miller-Rabin素数快速检测
    【数论算法理论与实现】
    洛谷P1141 01迷宫
  • 原文地址:https://www.cnblogs.com/chdy/p/12863066.html
Copyright © 2020-2023  润新知