zoukankan      html  css  js  c++  java
  • [NOI2011]

    来自FallDream的博客,未经允许,请勿转载,谢谢。


    省选完挂。但是善良的教练今天丢了一套NOI2011给我们训练 6道题233(虽然一道题做过了,一道题普及组的都会,就算是4道吧)

    熬了一天,总算啃掉了四题中的三题 D2T3那个牛逼的博弈论实在不知道怎么做,只好去看看题解233

    简单讲一下题解..

    D1T1兔农

    农夫栋栋近年收入不景气,正在他发愁如何能多赚点钱时,他听到隔壁的小朋友在讨论兔子繁殖的问题。

    问题是这样的:第一个月初有一对刚出生的小兔子,经过两个月长大后,这对兔子从第三个月开始,每个月初生一对小兔子。新出生的小兔子生长两个月后又能每个月生出一对小兔子。问第n个月有多少只兔子?

    聪明的你可能已经发现,第n个月的兔子数正好是第n个Fibonacci(斐波那契)数。栋栋不懂什么是Fibonacci数,但他也发现了规律:第i+2个月的兔子数等于第i个月的兔子数加上第i+1个月的兔子数。前几个月的兔子数依次为:

    1 1 2 3 5 8 13 21 34 …

    栋栋发现越到后面兔子数增长的越快,期待养兔子一定能赚大钱,于是栋栋在第一个月初买了一对小兔子开始饲养。

    每天,栋栋都要给兔子们喂食,兔子们吃食时非常特别,总是每k对兔子围成一圈,最后剩下的不足k对的围成一圈,由于兔子特别害怕孤独,从第三个月开始,如果吃食时围成某一个圈的只有一对兔子,这对兔子就会很快死掉。

    我们假设死去的总是刚出生的兔子,那么每个月的兔子数仍然是可以计算的。例如,当k=7时,前几个月的兔子数依次为:

    1 1 2 3 5 7 12 19 31 49 80 …

    给定n,你能帮助栋栋计算第n个月他有多少对兔子么?由于答案可能非常大,你只需要告诉栋栋第n个月的兔子对数除p的余数即可。

    1s/256MB   n<=10^18 k<=10^6 p<=10^9

    上来就刚这道题 但是不会.. 仔细想想没有那么复杂

    在一个点从1变成0之后,假设这个1之前的数字是x,之后的序列就变成了x,x,2x,3x,恰好是一个斐波那契数列!

    这种斐波那契数列不同的显然不超过k个,之后就会出现循环节。推到这里,解法就比较显然了。

    先暴力求出斐波那契数列膜k意义下的每个数值最小的出现位置,然后找到第一个1。

    之后我们不断拿出1之前的数字,用exgcd求它下一次变成1的时候,也就是它关于k的逆元,那么它下次出现1的位置就是这个逆元在斐波那契数列的第一次的出现位置。

    我们对一个数求解的时候给它打一个标记,一旦我们找到了已经求解过的数,说明找到了循环节。

    但是我们还要支持-1操作,所以考虑给斐波那契矩阵加一维1.  

    $egin{equation}
    left[
    egin{matrix}
    fi\
    f_{i-1}\
    1
    end{matrix}
    ight]
    end{equation}$*$egin{equation}
    left[
    egin{matrix}
    1&1&0\
    1&0&0\
    0&0&1&
    end{matrix}
    ight]
    end{equation}$=$egin{equation}
    left[
    egin{matrix}
    f_{i+1}\
    fi\
    1
    end{matrix}
    ight]
    end{equation}$

    $egin{equation}
    left[
    egin{matrix}
    fi\
    f_{i-1}\
    1
    end{matrix}
    ight]
    end{equation}$*$egin{equation}
    left[
    egin{matrix}
    1&0&-1\
    0&1&0\
    0&0&1&
    end{matrix}
    ight]
    end{equation}$=$egin{equation}
    left[
    egin{matrix}
    fi-1\
    f_{i-1}\
    1
    end{matrix}
    ight]
    end{equation}$

    用这两个矩阵就可以求出循环节的转移矩阵,然后直接快速幂就行啦。

    一开始没想到要加一维 后来乱改 应该是我写的最丑的代码之一..

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<map>
    #define ll long long
    #define MN 2000000
    using namespace std;
    inline ll read()
    {
        ll x = 0 , f = 1; char ch = getchar();
        while(ch < '0' || ch > '9'){ if(ch == '-') f = -1;  ch = getchar();}
        while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}
        return x * f;
    }
    ll n;
    int K,p,f[MN+5],mp[1000005];
    ll L[1000005];
    bool flag=0;
    
    struct Matrix 
    {
        int s[4][4];
        Matrix(){memset(s,0,sizeof(s));}
    }A,B,C,D,Mem[1000005];
    
    Matrix Mul(Matrix a,Matrix b,int mod)
    {
        Matrix c;
        for(int i=1;i<=3;i++)
            for(int j=1;j<=3;j++)
                for(int k=1;k<=3;k++)
                    c.s[i][j]=(c.s[i][j]+1LL*a.s[i][k]*b.s[k][j])%mod;
        return c;    
    }
    
    void Init()
    {
        memset(C.s,0,sizeof(C.s));
        C.s[1][1]=C.s[1][2]=C.s[2][1]=1;
        C.s[2][2]=0;C.s[3][3]=1;
    }
    
    Matrix MatPow(Matrix C,Matrix D,ll k,int mod)
    {
        for(;k;k>>=1,D=Mul(D,D,mod))
            if(k&1) C=Mul(C,D,mod);
        return C;
    }
    
    void vio(Matrix&D,ll k,int mod)
    {
        Init();
        for(;k;k>>=1,C=Mul(C,C,mod))
            if(k&1) D=Mul(C,D,mod);
    }
    
    inline ll exgcd(ll a,ll b,ll&x,ll&y)
    {
        if(!b){x=1;y=0;return a;}
        ll c=exgcd(b,a%b,x,y);
        ll t=x;x=y;y=t-a/b*x;
        return c;    
    }
    
    ll getinv(int x,int mod)
    {
        ll X,Y;
        if(1!=exgcd(x,mod,X,Y)) return 0; 
        return (X%mod+mod)%mod;
    }
    
    inline void Dec(Matrix&D)
    {
        memset(A.s,0,sizeof(A.s));
        A.s[1][1]=A.s[2][2]=A.s[3][3]=1;A.s[1][3]=p-1;  
        D=Mul(A,D,p);
        B.s[1][1]=0;
    }
    
    Matrix GetSq(int x)
    {
        Matrix E;int y=x;
        E.s[1][1]=E.s[2][2]=E.s[3][3]=1;
        do 
        {
            ll z=getinv(y,K);z=mp[z];
            vio(E,z,p);vio(B,z,K);Dec(E);
            y=B.s[2][1];
        }while(y!=x);
        return E;
    }
    
    void Solve(int x)
    {
        if(!n) return;
        if(L[x]) {ll tms=n/(L[x]-n);
                    if(tms)
                    {
                        Matrix T=GetSq(x);
                        T=MatPow(T,T,tms-1,p);
                        D=MatPow(T,D,1,p);
                    }n%=(L[x]-n);
                    flag=true;return;}
        L[x]=n;Mem[x]=D;ll y;
        if(!(y=getinv(x,K))) return;
        y=mp[y];if(y>n) return;
        n-=y;
        vio(D,y,p);vio(B,y,K);
    //    B.print();
        Dec(D);Solve(B.s[2][1]);
    }
    
    int main()
    {
        f[1]=f[2]=1;B.s[1][1]=B.s[2][1]=D.s[1][1]=D.s[2][1]=B.s[3][1]=D.s[3][1]=1;
        n=read();K=read();p=read();
        for(int i=3;i<=MN;i++) f[i]=(f[i-1]+f[i-2])%K;
        for(int i=3;i<=MN;i++) if(!mp[f[i]]) mp[f[i]]=i;
        if(!mp[1]||mp[1]>n) return vio(D,max(0LL,n-2),p),0*printf("%d
    ",D.s[1][1]); 
        vio(D,mp[1]-2,p);vio(B,mp[1]-2,K);n-=mp[1];Dec(D);
        Solve(B.s[2][1]);
        if(flag) 
        {
            memset(L,0,sizeof(L));
            Solve(B.s[2][1]);    
        } 
        vio(D,n,p);printf("%d
    ",D.s[1][1]);
        return 0;
    }

    D1T2 智能车比赛

    新一届智能车大赛在JL大学开始啦!比赛赛道可以看作是由n个矩形区域拼接而成(如下图所示),每个矩形的边都平行于坐标轴,第i个矩形区域的左下角和右上角坐标分别为(xi,1,yi,1)和(xi,2,yi,2)。

    题目保证:xi,1<xi,2=xi+1,1,且yi,1< yi,2,相邻两个矩形一定有重叠在一起的边(如图中虚线所示),智能车可以通过这部分穿梭于矩形区域之间。

    给定速度(意义不明)求起点到终点的最短时间。

    1s/256MB n<=2000

    发现到达的点一定是矩形的点,然后直接n^2dp就行了  计算几何比较烦

    但是我菜,写了建图最短路,差点T了,大家还是学学dp做法吧,比我的优很多...

    代码蛮贴一贴

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<queue>
    #define pa pair<double,int> 
    #define mp(x,y) make_pair(x,y)
    #define MN 8005
    #define FROM 8002
    #define TO 8001
    #define eps 1e-7
    #define INF 2000000000
    using namespace std;
    inline int read()
    {
        int x = 0 , f = 1; char ch = getchar();
        while(ch < '0' || ch > '9'){ if(ch == '-') f = -1;  ch = getchar();}
        while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}
        return x * f;
    }
    inline double sqr(double x){return x*x;}
    struct P
    {
        double x,y;    
        P(double _x=0,double _y=0):x(_x),y(_y){}
        double operator^(const P&b){return x*b.y-y*b.x;}
        P operator-(const P&b){return P(x-b.x,y-b.y);}
        friend double dis(P a,P b){return sqrt(sqr(a.x-b.x)+sqr(a.y-b.y));} 
    }S,T;
    int U[MN+5],D[MN+5],X[MN+5];
    struct L
    {    
        P p,v;
        L(){}
        L(P a,P b):p(a),v(b){}
        bool Left(P x){return (v^(x-p))>-eps;}
        bool Right(P x){return (v^(x-p))<eps;}
    };
    struct edge{int to,next;double f;}e[MN*100+5];
    double v,d[MN+5];
    int n,cnt=0,head[MN+5];
    priority_queue<pa,vector<pa>,greater<pa> >q;
    inline void ins(int f,int t,double w)
    {
    //    cout<<"ins"<<f<<" "<<t<<" "<<w<<endl;
        e[++cnt]=(edge){t,head[f],w};head[f]=cnt;
        e[++cnt]=(edge){f,head[t],w};head[t]=cnt;
    }
    
    void SolveLeft(int R,int from,P x)
    {
        L up(x,P(0,INF)),down(x,P(0,-INF));
        for(register int i=R;~i;--i)
        {
            P u=P(X[i],U[i]),d=P(X[i],D[i]); 
            if(up.Left(u)&&down.Right(u))
                ins(from,n+1+i,dis(u,x));
            if(up.Left(d)&&down.Right(d))
                ins(from,i,dis(d,x));
            if(up.Left(u)) up=L(x,u-x);
            if(down.Right(d)) down=L(x,d-x);
        }
    }
    
    void SolveRight(int Le,int from,P x)
    {
        L up(x,P(0,INF)),down(x,P(0,-INF));
        for(register int i=Le;i<=n;++i)
        {
            P u=P(X[i],U[i]),d=P(X[i],D[i]); 
            if(up.Right(u)&&down.Left(u))
                ins(from,n+1+i,dis(u,x));
            if(up.Right(d)&&down.Left(d))
                ins(from,i,dis(d,x));
            if(up.Right(u)) up=L(x,u-x);
            if(down.Left(d)) down=L(x,d-x);
        }
    }
    
    void dij()
    {
        memset(d,127,sizeof(d));d[FROM]=0;
        q.push(mp(0,FROM));
        while(!q.empty())
        {
            while(!q.empty()&&q.top().first!=d[q.top().second]) q.pop();
            if(q.empty()) break;
            int x=q.top().second;q.pop();
            for(int i=head[x];i;i=e[i].next)
                if(e[i].f+d[x]<d[e[i].to])
                {
                    d[e[i].to]=d[x]+e[i].f;
                    q.push(mp(d[e[i].to],e[i].to));    
                }
        }
    }
    
    int main()
    {
        n=read();
        U[0]=INF;D[0]=-INF;
        for(register int i=1;i<=n;i++)
        {
            int x1=read(),y1=read(),x2=read(),y2=read();
            X[i-1]=x1;X[i]=x2;
            U[i-1]=min(U[i-1],y2);
            D[i-1]=max(D[i-1],y1);
            U[i]=y2;D[i]=y1;
        }
        S.x=read();S.y=read();T.x=read();T.y=read();
        for(register int i=0;i<=n;i++)
        {
            if(i) SolveLeft(i-1,n+1+i,P(X[i],U[i])),
                  SolveLeft(i-1,i,P(X[i],D[i]));    
            if(i<n) SolveRight(i+1,n+1+i,P(X[i],U[i])),
                    SolveRight(i+1,i,P(X[i],D[i]));
        }
        register int i=0,j=0;bool flag=1;
        for(;X[i]<S.x;++i);    
        for(;X[j]<T.x;++j);
        flag&=(i==j);
        if(X[i]==S.x)
        { 
            ins(i,FROM,dis(P(X[i],D[i]),S)),ins(i+n+1,FROM,dis(S,P(X[i],U[i])));
            if(S.y>=D[i]&&S.y<=U[i]&&i>0) 
                if(i>0)SolveLeft(i-1,FROM,S);
        }
        else if(i>0)SolveLeft(i-1,FROM,S);
        for(;X[i]==S.x;++i);if(i<n)SolveRight(i,FROM,S);
        if(X[j]==T.x) 
        {
            ins(j,TO,dis(T,P(X[j],D[j]))),ins(j+n+1,TO,dis(T,P(X[j],U[j])));
            if(T.y>=D[j]&&T.y<=U[j]&&j>0) 
                if(j>0)SolveLeft(j-1,TO,T);
        }
        else if(j>0)SolveLeft(j-1,TO,T);
        for(;X[j]==T.x;++j);if(j<n)SolveRight(j,TO,T);
        dij();double v;scanf("%lf",&v);    
        if(i==j&&flag) d[TO]=min(d[TO],dis(S,T));
        printf("%.10lf
    ",d[TO]/v);
        return 0;
    }

    D1T3阿狸的打字机 

    以前做的题目 戳这里

    D2T1道路修建

    在 W 星球上有 n 个国家。为了各自国家的经济发展,他们决定在各个国家 之间建设双向道路使得国家之间连通。但是每个国家的国王都很吝啬,他们只愿 意修建恰好 n – 1 条双向道路。 每条道路的修建都要付出一定的费用,这个费用等于道路长度乘以道路两端 的国家个数之差的绝对值。例如,在下图中,虚线所示道路两端分别有 2 个、4 个国家,如果该道路长度为 1,则费用为 1×|2 – 4|=2。图中圆圈里的数字表示国 家的编号。

    由于国家的数量十分庞大,道路的建造方案有很多种,同时每种方案的修建 费用难以用人工计算,国王们决定找人设计一个软件,对于给定的建造方案,计 算出所需要的费用。请你帮助国王们设计一个这样的软件。

    n<=1000000  1s/256MB

    普及组水平的题目...

    #include<iostream>
    #include<cstdio>
    #define MN 1000000
    #define ll long long
    using namespace std;
    inline int read()
    {
        int x = 0 , f = 1; char ch = getchar();
        while(ch < '0' || ch > '9'){ if(ch == '-') f = -1;  ch = getchar();}
        while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}
        return x * f;
    }
     
    int n,head[MN+5],cnt=0,size[MN+5];
    struct edge{int to,next,w;}e[MN*2+5];
    ll ans=0;
    inline void ins(int f,int t,int w){e[++cnt]=(edge){t,head[f],w};head[f]=cnt;}
    inline int abs(int x){return x<0?-x:x;}
    void dfs(int x,int f)
    {
        size[x]=1;
        for(int i=head[x];i;i=e[i].next)
            if(e[i].to!=f)
            {
                dfs(e[i].to,x);
                size[x]+=size[e[i].to];
                ans+=1LL*e[i].w*abs(size[e[i].to]-(n-size[e[i].to]));
            }
    }
     
    int main()
    {
        n=read();
        for(int i=1;i<n;i++) 
        {
            int x=read(),y=read(),w=read();
            ins(x,y,w);ins(y,x,w);
        }
        dfs(1,0);
        printf("%lld
    ",ans);
        return 0;
    }

    D2T2 Noi嘉年华

    NOI2011 在吉林大学开始啦!为了迎接来自全国各地最优秀的信息学选手,吉林大学决定举办两场盛大的 NOI 嘉年华活动,分在两个不同的地点举办。每个嘉年华可能包含很多个活动,而每个活动只能在一个嘉年华中举办。

    现在嘉年华活动的组织者小安一共收到了 n个活动的举办申请,其中第 i 个活动的起始时间为 Si,活动的持续时间为Ti。这些活动都可以安排到任意一个嘉年华的会场,也可以不安排。

    小安通过广泛的调查发现,如果某个时刻,两个嘉年华会场同时有活动在进行(不包括活动的开始瞬间和结束瞬间),那么有的选手就会纠结于到底去哪个会场,从而变得不开心。所以,为了避免这样不开心的事情发生,小安要求不能有两个活动在两个会场同时进行(同一会场内的活动可以任意进行)。

    另外,可以想象,如果某一个嘉年华会场的活动太少,那么这个嘉年华的吸引力就会不足,容易导致场面冷清。所以小安希望通过合理的安排,使得活动相对较少的嘉年华的活动数量最大。

    此外,有一些活动非常有意义,小安希望能举办,他希望知道,如果第i 个活动必须举办(可以安排在两场嘉年华中的任何一个),活动相对较少的嘉年华的活动数量的最大值。

    n<=200  1s/256MB

    这道题看起来很可做  但是啃了很久做不出来  还好yy出了一个比较靠谱的dp方程,总算过了  差点忍不住去看题解了233

    离散时间点,然后f[i][j]表示前i个时间点其中一个嘉年华举办j场活动,另一场最多举办几场,转移比较显然。 g[i][j]表示后.....

    令h[i][j]表示时间点i到j的区间最多能办几场活动,那么对于每一个时间段x-y,答案是Ans[x][y]=max(min(f[x-1][i]+h[x][y]+g[y+1][k-i],k)) 后面那一串显然可以二分。

    所以处理完Ans数组之后,每个询问只要去查一个最大值就行了。复杂度n^3logn

    貌似可以借助单调性做到n^3   但是莫名没有我跑的快...

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #define MN 400
    #define INF 1000000000 
    using namespace std;
    inline int read()
    {
        int x = 0 , f = 1; char ch = getchar();
        while(ch < '0' || ch > '9'){ if(ch == '-') f = -1;  ch = getchar();}
        while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}
        return x * f;
    }
    
    int f[MN+5][MN+5],g[MN+5][MN+5],h[MN+5][MN+5],p[MN+5],Ans[MN+5][MN+5],tot=0,n,m=1;
    struct eve{int b,e;}e[MN+5];
    
    int main()
    {
        n=read();
        for(int i=1;i<=n;i++)
        {
            e[i].b=read();
            e[i].e=e[i].b+read()-1;    
            p[++tot]=e[i].b;
            p[++tot]=e[i].e;
        }
        sort(p+1,p+tot+1);
        for(int i=2;i<=tot;i++)
            if(p[i]!=p[i-1]) p[++m]=p[i];
        for(int i=1;i<=n;i++)
        {
            e[i].b=lower_bound(p+1,p+m+1,e[i].b)-p;
            e[i].e=lower_bound(p+1,p+m+1,e[i].e)-p;
            h[e[i].b][e[i].e]++;
        } 
        for(int len=2;len<=m;len++)
            for(int i=1;i+len-1<=m;i++)
            {
                int j=i+len-1;
                h[i][j]=h[i][j]+h[i+1][j]+h[i][j-1]-h[i+1][j-1]; 
            }
        for(int i=0;i<=m+1;i++)
            for(int j=0;j<=n;j++) f[i][j]=g[i][j]=-INF;
        f[0][0]=g[m+1][0]=0;
        for(int i=1;i<=m;i++)
            for(int k=0;k<=n;k++)
            {
                for(int j=0;j<i;j++)
                    if(h[j+1][i]<=k)
                        f[i][k]=max(f[i][k],f[j][k-h[j+1][i]]);
                f[i][k]=max(f[i][k],f[i-1][k]);
                if(f[i][k]>=0) f[i][f[i][k]]=max(f[i][f[i][k]],k);
            }
        for(int i=m;i;--i)
            for(int k=0;k<=n;k++)
            {
                for(int j=i+1;j<=m+1;j++)
                    if(h[i][j-1]<=k)
                        g[i][k]=max(g[i][k],g[j][k-h[i][j-1]]);
                g[i][k]=max(g[i][k],g[i+1][k]);
                if(g[i][k]>=0) g[i][g[i][k]]=max(k,g[i][g[i][k]]);
            }            
        int ans=0;
        for(int i=1;i<=n;i++)
            ans=max(ans,min(i,f[m][i]));
        printf("%d
    ",ans);
        for(int i=0;i<=m;i++)
            for(int j=i+1;j<=m+1;j++)
            {
                int l=1,r=n,ans=0,mid;
                while(l<=r)
                {
                    mid=l+r>>1;bool flag=false;
                    for(int k=0;k<=mid;k++)
                        if(f[i][k]+g[j][mid-k]+h[i+1][j-1]>=mid)
                        {
                            flag=true;
                            break;
                        }
                    if(flag) ans=mid,l=mid+1;
                    else r=mid-1;
                }
                Ans[i][j]=ans;
            }
        for(int i=1;i<=n;i++)
        {
            int ans=0;
            for(int j=0;j<e[i].b;j++)
                for(int k=e[i].e+1;k<=m+1;k++)
                    ans=max(ans,Ans[j][k]);    
            printf("%d
    ",ans);
        }
        return 0;
    }

    D2T3

    这些天,兔兔和蛋蛋喜欢上了一种新的棋类游戏。 这个游戏是在一个n行m列的棋盘上进行的。游戏开始之前,棋盘上有一个格子是空的,其它的格子中都放置了一枚棋子,棋子或者是黑色,或者是白色。 每一局游戏总是兔兔先操作,之后双方轮流操作,具体操作为:

    兔兔每次操作时,选择一枚与空格相邻的白色棋子,将它移进空格。

    蛋蛋每次操作时,选择一枚与空格相邻的黑色棋子,将它移进空格。

    第一个不能按照规则操作的人输掉游戏。为了描述方便,下面将操作“将第x行第y列中的棋子移进空格中”记为M(x,y)。 例如下面是三个游戏的例子。

    最近兔兔总是输掉游戏,而且蛋蛋格外嚣张,于是兔兔想请她的好朋友——你——来帮助她。她带来了一局输给蛋蛋的游戏的实录,请你指出这一局游戏中所有她“犯错误”的地方。 注意:

    两个格子相邻当且仅当它们有一条公共边。

    兔兔的操作是“犯错误”的,当且仅当,在这次操作前兔兔有必胜策略,而这次操作后蛋蛋有必胜策略。

    丢个链接:这里有很详细的题解 

    #include<cstdio>
    #include<iostream>
    #define MN 1600
    #define MC 40
    using namespace std;
    inline int read()
    {
        int x=0;char ch=getchar();
        while(ch<'0'||ch>'9')ch=getchar();
        while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
        return x;
    }
    int n,m,head[MN+5],cnt=0,match[MN+5],mark[MN+5],fx,fy,s[MC+5][MC+5],tot=0,cn=0,Ans[MN+5];
    struct edge{int to,next;}e[MN*4+5];
    char st[MC+5][MC+5];
    bool ban[MN+5];
    const int dis[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
    inline void ins(int f,int t){e[++cnt]=(edge){t,head[f]};head[f]=cnt;}
    inline int num(int x,int y){return (x-1)*m+y;}
    
    bool Dfs(int x)
    {
        for(int i=head[x];i;i=e[i].next)
            if(mark[e[i].to]!=tot&&!ban[e[i].to])
            {
                mark[e[i].to]=tot;
                if(!match[e[i].to]||Dfs(match[e[i].to]))
                {
                    match[x]=e[i].to;
                    match[e[i].to]=x;
                    return true;
                }
            }
        return false;
    }
    
    int calc(int x)
    {
        ban[x]=1;
        if(!match[x])return 0;
        int rt=match[x];
        match[rt]=match[x]=0;
        return ++tot,!Dfs(rt);
    }
    
    int main()
    {
        n=read();m=read();
        for(int i=1;i<=n;i++) scanf("%s",st[i]+1);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                if(st[i][j]=='.') fx=i,fy=j;
                else s[i][j]=st[i][j]=='X'?0:1;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                for(int k=0;k<4;k++)
                {
                    int x=i+dis[k][0],y=j+dis[k][1];
                    if(x<1||y<1||x>n||y>m||s[i][j]==s[x][y]) continue;
                    ins(num(i,j),num(x,y));
                }
        for(int i=1;i<=n*m;++i) if(!match[i])++tot,Dfs(i);
        int q=read();
        for(int i=1;i<=q;++i)
        {
            int res1=calc(num(fx,fy));
            fx=read(),fy=read();
            int res2=calc(num(fx,fy));
            if(res1&&res2) Ans[++cn]=i;
            fx=read();fy=read();
        }
        cout<<cn<<endl;
        for(int i=1;i<=cn;i++)printf("%d
    ",Ans[i]);
        return 0;
    }
  • 相关阅读:
    Codeforces 1316B String Modification
    Codeforces 1305C Kuroni and Impossible Calculation
    Codeforces 1305B Kuroni and Simple Strings
    Codeforces 1321D Navigation System
    Codeforces 1321C Remove Adjacent
    Codeforces 1321B Journey Planning
    Operating systems Chapter 6
    Operating systems Chapter 5
    Abandoned country HDU
    Computer HDU
  • 原文地址:https://www.cnblogs.com/FallDream/p/noi2011.html
Copyright © 2011-2022 走看看