专项测试(图论2)

改题历程极其艰辛

再一次挫伤了我的自信心......

T1 收藏家

对时间建立节点,最大流就行了

AC_code
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define fo(i,x,y) for(int i=(x);i<=(y);i++)
#define fu(i,x,y) for(int i=(x);i>=(y);i--)
int read(){
    int s=0,t=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')t=-1;ch=getchar();}
    while(isdigit(ch)){s=(s<<3)+(s<<1)+ch-'0';ch=getchar();}
    return s*t;
}
const int inf=0x3f3f3f3f3f3f3f3f;
const int N=10005;
int T,n,m,s=9001,t=9002,a[N];
struct E{int to,nxt,val;}e[N*10];
int head[N],hea[N],rp=1;
void clear(){
    memset(head,0,sizeof(head));rp=1;
}
void add_edg(int x,int y,int z){
    e[++rp].to=y;e[rp].val=z;
    e[rp].nxt=head[x];head[x]=rp;
}
int dis[N];
bool bfs(){
    memset(dis,0x3f,sizeof(dis));
    memcpy(head,hea,sizeof(hea));
    queue<int> q;while(!q.empty())q.pop();
    q.push(s);dis[s]=0;
    while(!q.empty()){
        int x=q.front();q.pop();
        for(int i=head[x];i;i=e[i].nxt){
            int y=e[i].to;
            if(!e[i].val||dis[y]<=dis[x]+1)continue;
            dis[y]=dis[x]+1;q.push(y);
            if(y==t)return true;
        }
    }
    return false;
}
int dfs(int x,int in){
    if(x==t)return in;
    int rest=in,go=0;
    for(int i=head[x];i;head[x]=i=e[i].nxt){
        int y=e[i].to;
        if(!e[i].val||dis[y]!=dis[x]+1)continue;
        go=dfs(y,min(rest,e[i].val));
        if(go)e[i].val-=go,e[i^1].val+=go,rest-=go;
        else dis[y]=0;
        if(!rest)break;
    }
    return in-rest;
}
int dinic(){
    int ret=0;memcpy(hea,head,sizeof(head));
    while(bfs())ret+=dfs(s,inf);
    return ret;
}
int now[N],cn,p=1;
signed main(){
    T=read();
    while(T--){
        clear();
        cn=n=read();m=read();
        fo(i,1,n)now[i]=i;
        fo(i,1,n){
            a[i]=read();
            if(a[i]==0)continue;
            add_edg(s,i,1);
            add_edg(i,s,0);
        }
        fo(i,1,m){
            int x=read(),y=read();
            add_edg(now[x],now[y],1);
            add_edg(now[y],now[x],1);
            if(x!=1){add_edg(now[x],++cn,a[x]);add_edg(cn,now[x],0);now[x]=cn;}
            if(y!=1){add_edg(now[y],++cn,a[y]);add_edg(cn,now[y],0);now[y]=cn;}
        }
        add_edg(1,t,a[1]);add_edg(t,1,0);
        printf("%lld\n",dinic());
    }
    return 0;
}

T2 旅行

发现转移方程是个分数规划,于是二分,用最大闭合子图判断

AC_code
#include<bits/stdc++.h>
using namespace std;
#define double long double
#define int long long
#define fo(i,x,y) for(int i=(x);i<=(y);i++)
#define fu(i,x,y) for(int i=(x);i>=(y);i--)
int read(){
    int s=0,t=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')t=-1;ch=getchar();}
    while(isdigit(ch)){s=(s<<3)+(s<<1)+ch-'0';ch=getchar();}
    return s*t;
}
const double eps=1e-10;
const double inf=1e9;
const int N=55;
const int M=505;
const int K=2005;
int n,m,k;
struct E{int to,nxt,id;}e[M*2],ek[K*2];
int head[N],hk[M],rp,rk,du[N];
void add_e(int x,int y,int id){
    e[++rp].to=y;e[rp].id=id;du[y]++;
    e[rp].nxt=head[x];head[x]=rp;
}
void add_k(int x,int y){
    ek[++rk].to=y;ek[rk].nxt=hk[x];hk[x]=rk;
}
int ji[M],ys[M],cj;
double dp[N],f[M];
struct W{
    int s=501,t=502;
    struct E{int to,nxt;double val;}e[K*4];
    int head[M],hea[M],rp=1;
    void add_edg(int x,int y,double z){
        e[++rp].to=y;e[rp].val=z;
        e[rp].nxt=head[x];head[x]=rp;
    }
    int dis[M];
    bool bfs(){
        memset(dis,0x3f,sizeof(dis));
        memcpy(head,hea,sizeof(hea));
        queue<int> q;while(!q.empty())q.pop();
        q.push(s);dis[s]=0;
        while(!q.empty()){
            int x=q.front();q.pop();
            // cout<<"X "<<x<<endl;
            for(int i=head[x];i;i=e[i].nxt){
                int y=e[i].to;
                // if(x==2)cout<<x<<" "<<y<<" "<<e[i].val<<" "<<dis[y]<<endl;
                if(fabs(e[i].val)<eps||dis[y]<=dis[x]+1)continue;
                dis[y]=dis[x]+1;q.push(y);
                if(y==t)return true;
            }
        }
        return false;
    }
    double dfs(int x,double in){
        if(x==t)return in;
        double rest=in,go=0;
        for(int i=head[x];i;head[x]=i=e[i].nxt){
            int y=e[i].to;
            if(fabs(e[i].val)<eps||dis[y]!=dis[x]+1)continue;
            go=dfs(y,min(rest,e[i].val));
            if(go)e[i].val-=go,e[i^1].val+=go,rest-=go;
            else dis[y]=0;
            if(fabs(rest)<eps)break;
        }
        return in-rest;
    }
    double dinic(){
        double ret=0;
        memset(head,0,sizeof(head));rp=1;
        fo(i,1,cj)ys[ji[i]]=i;
        // cout<<"one"<<endl;
        fo(i,1,cj){
            // cout<<i<<" "<<ji[i]<<" "<<f[ji[i]]<<endl;
            if(f[ji[i]]>eps){
                ret+=f[ji[i]];
                add_edg(s,i,f[ji[i]]);
                add_edg(i,s,0);
            }
            else {
                add_edg(i,t,-f[ji[i]]);
                add_edg(t,i,0);
            }
        }
        fo(x,1,cj){
            for(int i=hk[ji[x]];i;i=ek[i].nxt){
                int y=ys[ek[i].to];
                // cout<<"SB"<<" "<<x<<" "<<ji[x]<<" "<<ji[y]<<" "<<inf<<" "<<"ZZ"<<endl;
                add_edg(x,y,inf);
                add_edg(y,x,0);
            }
        }
        // cout<<ret<<endl;
        // cout<<head[1]<<endl;
        memcpy(hea,head,sizeof(head));
        while(bfs())ret-=dfs(s,inf);//cout<<"ZZ"<<endl;
        // cout<<ret<<endl;
        return ret;
    }
}w;
int tpn[N],ipn[N],cnt;
void topu(){
    queue<int> q;while(!q.empty())q.pop();
    fo(i,1,n)if(!du[i])q.push(i);
    while(!q.empty()){
        int x=q.front();q.pop();
        tpn[x]=++cnt;ipn[cnt]=x;
        for(int i=head[x];i;i=e[i].nxt){
            int y=e[i].to;
            if(!--du[y])q.push(y);
        } 
    }
}
signed main(){
    n=read();m=read();k=read();
    fo(i,1,m){
        int x=read(),y=read();
        add_e(x,y,i);
    }
    fo(i,1,k){
        int x=read(),y=read();
        add_k(x,y);
    }
    topu();
    // cout<<"SB"<<endl;
    fu(o,cnt,1){
        int x=ipn[o];cj=0;
        if(!head[x]){dp[x]=0;continue;}
        double l=0,r=0,mid;
        for(int i=head[x];i;i=e[i].nxt){
            int y=e[i].to;
            ji[++cj]=e[i].id;
            r=max(r,dp[y]+1);
        }
        // cout<<l<<" "<<r<<endl;
        while(r-l>eps){
            mid=(r+l)/2;
            for(int i=head[x];i;i=e[i].nxt){
                int y=e[i].to;
                f[e[i].id]=dp[y]+1-mid;
            }
            if(w.dinic()>=eps)l=mid;
            else r=mid;
        }
        dp[x]=l;
        // cout<<"dp"<<" "<<x<<" "<<dp[x]<<endl;
    }
    printf("%.10Lf",dp[1]);
}

T3 字符串

\(LCT\)维护\(SAM\),于是乎,我们需要一颗主席树,维护最长匹配段

注意,只要用到的节点,就\(splay\)一下,防止没有标记下放

AC_code
#include<bits/stdc++.h>
using namespace std;
#define fo(i,x,y) for(int i=(x);i<=(y);i++)
#define fu(i,x,y) for(int i=(x);i>=(y);i--)
int read(){
    int s=0,t=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')t=-1;ch=getchar();}
    while(isdigit(ch)){s=s*10+ch-'0';ch=getchar();}
    return s*t;
}
const int N=1e5+5;
int rt[N],n,m,lans,R;
struct ZXS{
    struct POT{int mx,ls,rs;}tr[N*400];
    int seg;
    void pushup(int x){tr[x].mx=max(tr[tr[x].ls].mx,tr[tr[x].rs].mx);}
    void ins(int pr,int &x,int l,int r,int pos,int v){
        x=++seg;tr[x]=tr[pr];
        if(l==r)return tr[x].mx=v,void();
        int mid=l+r>>1;
        if(pos<=mid)ins(tr[pr].ls,tr[x].ls,l,mid,pos,v);
        else ins(tr[pr].rs,tr[x].rs,mid+1,r,pos,v);
        pushup(x);return ;
    }
    int query(int x,int l,int r,int ql,int qr){
        if(!x)return 0;
        if(ql<=l&&r<=qr)return tr[x].mx;
        int mid=l+r>>1,ret=0;
        if(ql<=mid)ret=max(ret,query(tr[x].ls,l,mid,ql,qr));
        if(qr>mid)ret=max(ret,query(tr[x].rs,mid+1,r,ql,qr));
        return ret;
    }
}zxs;
struct LCT{
    struct POT{int len,lst,tag,son[2],fa;}tr[N*2];
    int pth[N*2],pt;
    void pusht(int x,int v){tr[x].lst=tr[x].tag=v;}
    void pushdown(int x){
        if(!tr[x].tag)return ;
        if(tr[x].son[0])pusht(tr[x].son[0],tr[x].tag);
        if(tr[x].son[1])pusht(tr[x].son[1],tr[x].tag);
        tr[x].tag=0;
    }
    bool nroot(int x){return tr[tr[x].fa].son[0]==x||tr[tr[x].fa].son[1]==x;}
    int get(int x){return tr[tr[x].fa].son[1]==x;}
    void rotate(int x){
        int y=tr[x].fa,z=tr[y].fa;
        int xpos=get(x),ypos=get(y);
        if(nroot(y))tr[z].son[ypos]=x;
        tr[x].fa=z;tr[y].fa=x;
        tr[y].son[xpos]=tr[x].son[xpos^1];
        tr[tr[x].son[xpos^1]].fa=y;
        tr[x].son[xpos^1]=y;
    }
    void splay(int x){
        int now=x;pth[++pt]=now;
        while(nroot(now))pth[++pt]=now=tr[now].fa;
        while(pt)pushdown(pth[pt--]);
        while(nroot(x)){
            int y=tr[x].fa,z=tr[y].fa;
            int xpos=get(x),ypos=get(y);
            if(nroot(y)){
                if(xpos==ypos)rotate(y);
                else rotate(x);
            }
            rotate(x);
        }
    }
    void access(int x,int id){
        for(int y=0,now=x;now;y=now,now=tr[now].fa){
            splay(now);tr[now].son[1]=y;
            if(now!=1&&tr[now].lst&&zxs.query(rt[id],1,R,tr[now].lst,tr[now].lst)<tr[now].len)
                zxs.ins(rt[id],rt[id],1,R,tr[now].lst,tr[now].len);
        }
    }
    void link(int x,int y){
        splay(x);splay(y);tr[x].fa=y;
    }
    void links(int x,int y){
        splay(x);splay(y);tr[x].fa=y;
        tr[y].son[1]=x;
    }
    bool cut(int x,int y){
        bool ret=false;
        splay(x);splay(y);tr[x].fa=0;
        if(tr[y].son[1]==x)tr[y].son[1]=0,ret=true;
        return ret;
    }
}lct;
struct SAM{
    struct POT{int len,son[26],fail;}tr[N*2];
    int seg,las;
    SAM(){seg=las=1;}
    void ins(int c,int id){
        int p=las,np=++seg;las=np;
        lct.tr[np].len=tr[np].len=tr[p].len+1;
        while(p&&!tr[p].son[c])tr[p].son[c]=np,p=tr[p].fail;
        if(!p){tr[np].fail=1;lct.link(np,1);}
        else {
            int q=tr[p].son[c];
            if(tr[q].len==tr[p].len+1){tr[np].fail=q;lct.link(np,q);}
            else {
                int nq=++seg;lct.splay(q);
                tr[nq]=tr[q];lct.tr[nq]=lct.tr[q];
                lct.tr[nq].son[0]=lct.tr[nq].son[1]=lct.tr[nq].fa=0;
                if(lct.cut(q,tr[q].fail))lct.links(nq,tr[q].fail);
                else lct.link(nq,tr[q].fail);
                tr[nq].len=lct.tr[nq].len=tr[p].len+1;
                tr[np].fail=tr[q].fail=nq;
                lct.link(np,nq);lct.links(q,nq);
                while(p&&tr[p].son[c]==q)tr[p].son[c]=nq,p=tr[p].fail;
            }
        }
        rt[id]=rt[id-1];lct.access(las,id);lct.splay(las);lct.pusht(las,id);
    }
}sam;
int work(int s,int t){
    // if(s>t)return 0;
    int l=0,r=t-s,mid;
    while(l<r){
        mid=l+r+1>>1;
        if(zxs.query(rt[t],1,R,s+mid-1,t)>=mid)l=mid;
        else r=mid-1;
    }
    return l;
}
char a[N];
signed main(){
    scanf("%s",a+1);m=read();
    n=strlen(a+1);R=n+m;
    fo(i,1,n)sam.ins(a[i]-'a',i);
    while(m--){
        int tp=read(),l,r;
        if(tp==1){
            scanf("%s",a+1);a[1]=(a[1]-'a'+lans)%26+'a';
            sam.ins(a[1]-'a',++n);
        }
        else {
            l=(read()-1+lans)%n+1,r=(read()-1+lans)%n+1;
            if(l>r)swap(l,r);
            printf("%d\n",lans=work(l,r));
        }
    }
}
posted @ 2021-12-27 17:14  fengwu2005  阅读(40)  评论(0编辑  收藏  举报