zoukankan      html  css  js  c++  java
  • 树上问题&图论模板整理

    去除过水的模板,包括但不限于dijkstra(甚至堆优化都被过滤了)、SPFA、kruskal、拓扑排序等。

    欧拉回路http://uoj.ac/problem/117

    #include<bits/stdc++.h>
    using namespace std;
    const int N=4e5+7;
    int n,m,tp,cnt,ecnt=1,in[N],ou[N],vis[N],hd[N],v[N],nxt[N],ans[N];
    void adde(int x,int y){v[++ecnt]=y,nxt[ecnt]=hd[x],hd[x]=ecnt;}
    void dfs(int u)
    {
        for(int &i=hd[u];i;i=nxt[i])
        {
            int y=v[i],j=i;
            if(!vis[j>>1])vis[j>>1]=1,dfs(y),ans[++cnt]=j;
        }
    }
    int main()
    {
        scanf("%d%d%d",&tp,&n,&m);
        int x,y;
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d",&x,&y),adde(x,y);
            if(tp==1)adde(y,x),in[x]++,in[y]++;
            else ecnt++,in[y]++,ou[x]++;
        }
        if(tp==1){for(int i=1;i<=n;i++)if(in[i]&1){puts("NO");return 0;}}
        else for(int i=1;i<=n;i++)if(in[i]!=ou[i]){puts("NO");return 0;}
        dfs(x);
        if(cnt!=m)puts("NO");
        else{
            puts("YES");
            for(int i=cnt;i;i--)printf("%d ",(ans[i]&1)?-(ans[i]>>1):(ans[i]>>1));
        }
    }

    混合图的欧拉路https://www.lydsy.com/JudgeOnline/problem.php?id=2095

    #include<bits/stdc++.h>
    using namespace std;
    const int N=4007,M=1e6+7;
    int n,m,mn=1e9,mx,cnt,tot,S=0,T=1001,hd[N],v[M],nxt[M],cap[M],lv[N];
    int st[N],ed[N],w1[N],w2[N],du[N],q[N];
    void add(int x,int y,int z)
    {
        v[++cnt]=y,nxt[cnt]=hd[x],cap[cnt]=z,hd[x]=cnt;
        v[++cnt]=x,nxt[cnt]=hd[y],cap[cnt]=0,hd[y]=cnt;
    }
    bool bfs()
    {
        int qs=0,qe=1;
        memset(lv,-1,sizeof lv);
        lv[q[0]=S]=0;
        while(qs<qe)
        {
            int u=q[qs++];
            if(u==T)break;
            for(int i=hd[u];i;i=nxt[i])
            if(cap[i]&&lv[v[i]]==-1)lv[v[i]]=lv[u]+1,q[qe++]=v[i];
        }
        return lv[T]!=-1;
    }
    int dfs(int u,int low)
    {
        if(u==T)return low;
        int sum=0,tmp;
        for(int i=hd[u];i;i=nxt[i])
        if(cap[i]&&lv[v[i]]==lv[u]+1)
        {
            tmp=dfs(v[i],min(low,cap[i]));
            low-=tmp,sum+=tmp;
            cap[i]-=tmp,cap[i^1]+=tmp;
        }
        if(!sum)lv[u]=-1;
        return sum;
    }
    int dinic()
    {
        int ret=0;while(bfs())ret+=dfs(S,1e9);
        return ret;
    }
    bool check(int mid)
    {
        memset(hd,0,sizeof hd);
        memset(du,0,sizeof du);
        tot=0,cnt=1;
        for(int i=1;i<=m;++i)
        {
            if(w1[i]<=mid)--du[st[i]],++du[ed[i]];
            if(w2[i]<=mid)add(ed[i],st[i],1);
        }
        for(int i=1;i<=n;++i)
        if(du[i]>0)tot+=du[i]/2,add(S,i,du[i]/2);else if(du[i]<0)add(i,T,-du[i]/2);
        for(int i=1;i<=n;++i)if(du[i]&1)return 0;
        if(dinic()==tot)return 1;
        return 0;
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d%d%d",&st[i],&ed[i],&w1[i],&w2[i]);
            if(w1[i]>w2[i])swap(w1[i],w2[i]),swap(st[i],ed[i]);
            mn=min(mn,w1[i]),mx=max(mx,w2[i]);
        }
        int l=mn,r=mx,ans=mx+1;
        while(l<=r)
        {
            int mid=l+r>>1;
            if(check(mid))ans=mid,r=mid-1;
            else l=mid+1;
        }
        if(ans==mx+1)puts("NIE");else printf("%d",ans);
    }

    强连通分量https://www.lydsy.com/JudgeOnline/problem.php?id=1654

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    const int N=1e4+10;
    int n,m,cnt,v[N*5],next[N*5],head[N];
    int q[N],top,low[N],dfn[N],sum[N],scc,ans;
    bool vis[N];
    void add(int x,int y)
    {v[++cnt]=y;next[cnt]=head[x];head[x]=cnt;}
    void tarjan(int u)
    {
        low[u]=dfn[u]=++cnt;
        q[++top]=u;vis[u]=1;
        for(int i=head[u];i;i=next[i])
        if(!dfn[v[i]])
        {
            tarjan(v[i]);
            low[u]=min(low[u],low[v[i]]);
        }
        else if(vis[v[i]])
        low[u]=min(low[u],dfn[v[i]]);
        int now=0;
        if(low[u]==dfn[u])
        {
            scc++;
            while(now!=u)
            {
                now=q[top--];
                vis[now]=0;
                sum[scc]++;
            }
        }
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        int x,y;
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d",&x,&y);
            add(x,y);
        }
        cnt=0;
        for(int i=1;i<=n;i++)
        if(!dfn[i])tarjan(i);
        for(int i=1;i<=scc;i++)
        if(sum[i]>1)
        ans++;
        printf("%d",ans);
    }

    求割点https://www.luogu.org/problemnew/show/P3388

    #include<bits/stdc++.h>
    using namespace std;
    const int N=2e5+7;
    int n,m,cnt=1,ans,v[N],nxt[N],hd[N],low[N],dfn[N],cut[N];
    void add(int x,int y){v[++cnt]=y,nxt[cnt]=hd[x],hd[x]=cnt;}
    void tarjan(int u,int pre)
    {
        int sum=0;bool flag=0;
        dfn[u]=low[u]=++cnt;
        for(int i=hd[u];i;i=nxt[i])
        if(i!=(pre^1))
        {
            if(!dfn[v[i]])
            {
                sum++;
                tarjan(v[i],i);
                low[u]=min(low[u],low[v[i]]);
                if(low[v[i]]>=dfn[u])flag=1;
            }
            else low[u]=min(low[u],dfn[v[i]]);
        }
        if(!pre&&sum>1||pre&&flag)cut[u]=1,ans++;
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1,x,y;i<=m;i++)scanf("%d%d",&x,&y),add(x,y),add(y,x);
        cnt=0;
        for(int i=1;i<=n;i++)if(!dfn[i])tarjan(i,0);
        printf("%d
    ",ans);
        for(int i=1;i<=n;i++)if(cut[i])printf("%d ",i);
    }

    圆方树https://www.luogu.org/problemnew/show/P4630

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N=2e5+7;
    vector<int>G1[N],G2[N];
    int n,m,tot,sum,tim,top,low[N],dfn[N],q[N],sz[N],val[N];
    ll ans;
    void tarjan(int u)
    {
        dfn[u]=low[u]=++tim,q[++top]=u;
        sz[u]=1,val[u]=-1;
        for(int i=0;i<G1[u].size();i++)
        if(!dfn[G1[u][i]])
        {
            int v=G1[u][i];
            tarjan(v),low[u]=min(low[u],low[v]);
            if(low[v]>=dfn[u])
            {
                G2[u].push_back(++tot),val[tot]=1;
                int x=0;
                do{
                    x=q[top--],G2[tot].push_back(x);
                    sz[tot]+=sz[x],val[tot]++;
                }while(x!=v);
                sz[u]+=sz[tot];
            }
        }
        else low[u]=min(low[u],dfn[G1[u][i]]);
    }
    void dfs(int u)
    {
        if(u<=n)ans+=1ll*(sum-1)*val[u];
        ans+=1ll*(sum-sz[u])*sz[u]*val[u];
        for(int i=0;i<G2[u].size();i++)
        ans+=1ll*(sum-sz[G2[u][i]])*sz[G2[u][i]]*val[u],dfs(G2[u][i]);
    }
    int main()
    {
        scanf("%d%d",&n,&m),tot=n;
        for(int i=1,x,y;i<=m;i++)scanf("%d%d",&x,&y),G1[x].push_back(y),G1[y].push_back(x);
        for(int i=1;i<=n;i++)if(!dfn[i])tarjan(i),sum=sz[i],dfs(i);
        printf("%lld",ans);
    }

    floyd判圈法https://codeforces.com/gym/101252/problem/D

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N=2e7;
    ll a,b,c,s,r,x,y; 
    int main()
    {
        freopen("input.txt","r",stdin);
        freopen("output.txt","w",stdout);
        cin>>a>>b>>c;
        x=y=1;
        while(s<N)
        {
            s++;
            y=(a*y+y%b)%c,y=(a*y+y%b)%c;
            x=(a*x+x%b)%c;
            if(x==y)break;
        }
        if(x!=y){puts("-1");return 0;}
        while(r<N)
        {
            r++;
            y=(a*y+y%b)%c;
            if(x==y)break;
        }
        if(x!=y){puts("-1");return 0;}
        s=0,y=1;
        while(x!=y&&s<N)
        {
            s++;
            y=(a*y+y%b)%c;
            x=(a*x+x%b)%c;
        }
        s+=r;
        if(x==y&&s<=N)cout<<s;
        else puts("-1");
        return 0;
    }

    kruskal重构树:NOI2018归程

    #include<bits/stdc++.h>
    #define mp make_pair
    using namespace std;
    typedef long long ll;
    const int N=2e6;
    struct path{int u,v,w;}a[N];
    struct edge{int v,nxt;ll w;}e[N];
    int n,m,cnt,tot,hd[N],fa[N],f[N][23],val[N],Q,K,S;
    ll d[N],minv[N];
    bool vis[N];
    priority_queue<pair<ll,int> >q;
    bool cmp(path a,path b){return a.w>b.w;}
    int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);}
    void add(int x,int y,ll z){e[++cnt]=(edge){y,hd[x],z};hd[x]=cnt;}
    void dijkstra()
    {
        memset(vis,0,sizeof vis);
        for(int i=2;i<=2*n;i++)d[i]=1e17;
        q.push(mp(0,1));
        while(!q.empty())
        {
            int u=q.top().second;q.pop();
            if(vis[u])continue;
            vis[u]=1;
            for(int i=hd[u];i;i=e[i].nxt)
            if(d[u]+e[i].w<d[e[i].v]&&!vis[e[i].v])
            d[e[i].v]=d[u]+e[i].w,q.push(mp(-d[e[i].v],e[i].v));
        }
    }
    void dfs(int u)
    {
        minv[u]=d[u];
        for(int i=hd[u];i;i=e[i].nxt)
        {
            f[e[i].v][0]=u;
            dfs(e[i].v);
            minv[u]=min(minv[u],minv[e[i].v]);
        }
    }
    void kruskal()
    {
        memset(hd,0,sizeof hd);cnt=0;
        tot=n;
        sort(a+1,a+m+1,cmp);
        for(int i=1;i<=n;i++)fa[i]=i;
        for(int i=1;i<=m;i++)
        {
            int x=find(a[i].u),y=find(a[i].v);
            if(x!=y)
            {
                val[++tot]=a[i].w;
                fa[x]=fa[y]=fa[tot]=tot;
                add(tot,x,0);add(tot,y,0);
            }
        }
        dfs(tot);
    }
    int main()
    {
        int T;scanf("%d",&T);
        while(T--)
        {
            memset(hd,0,sizeof hd);
            memset(f,0,sizeof f);
            cnt=0;
            scanf("%d%d",&n,&m);
            for(int i=1;i<=m;i++)
            {
                int x,y,w,h;
                scanf("%d%d%d%d",&x,&y,&w,&h);
                add(x,y,w);add(y,x,w);
                a[i]=(path){x,y,h};
            }
            dijkstra();
            kruskal();
            for(int j=1;(1<<j)<=tot;j++)
            for(int i=1;i<=tot;i++)
            f[i][j]=f[f[i][j-1]][j-1];
            scanf("%d%d%d",&Q,&K,&S);
            ll ans=0;
            while(Q--)
            {
                int vi,pi;
                scanf("%d%d",&vi,&pi);
                vi=(vi+K*ans-1)%n+1;
                pi=(pi+K*ans)%(S+1);
                for(int j=22;~j;j--)
                if(f[vi][j]&&val[f[vi][j]]>pi) 
                vi=f[vi][j];
                printf("%lld
    ",ans=minv[vi]);
            }
        }
    }

    基环树:NOIP2018旅行O(nlogn)

    #include<bits/stdc++.h>
    using namespace std;
    const int N=5e5+7;
    int n,m,top,k,cnt,cut,a[N],b[N],cir[N],s[N],g[N],vis[N];
    vector<int>v[N];
    inline int read()
    {
        int x=0,w=0;
        char ch=0;
        while(!isdigit(ch))w|=ch=='-',ch=getchar();
        while(isdigit(ch))x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
        return w?-x:x;
    }
    void dfs(int u,int fa)
    {
        a[++top]=u;
        for(int i=0;i<v[u].size();++i)if(v[u][i]!=fa)dfs(v[u][i],u);
    }
    void getcir(int x,int fa)
    {
        s[++top]=x;
        vis[x]=1;
        int sz=v[x].size();
        for(int i=0;i<sz;++i)
        if(v[x][i]!=fa)
        {
            if(vis[v[x][i]])
            {
                k=1;
                while(s[top]!=v[x][i])g[++cnt]=s[top--];
                g[++cnt]=v[x][i];
                return;
            }
            getcir(v[x][i],x);
            if(k)return;
        }
        vis[s[top--]]=0;
    }
    void dfs2(int x,int k,int fa)
    {
        a[++top]=x,vis[x]=1;
        int sz=v[x].size()-1;
        for(int i=0;i<=sz;++i)b[i]=v[x][i];
        v[x].clear();
        for(int i=0;i<=sz;++i)
        if(!vis[b[i]])v[x].push_back(b[i]);
        sz=v[x].size()-1;
        for(int i=0;i<=sz;++i)
        if(!vis[v[x][i]])
        {
            if(i==sz&&cir[v[x][i]]&&!cut&&v[x][i]>k&&cir[fa]){cut=1;return;}
            if(i<sz-1)dfs2(v[x][i],v[x][i+1],x);
            else if(i==sz)dfs2(v[x][i],k,x);
            else{
                int y=i+1;
                if(cir[v[x][y]]&&!cut&&v[x][y]>k&&cir[fa])dfs2(v[x][i],k,x);
                else dfs2(v[x][i],v[x][y],x);
            }
        }
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1,x,y;i<=m;i++)v[x=read()].push_back(y=read()),v[y].push_back(x);
        for(int i=1;i<=n;i++)sort(v[i].begin(),v[i].end());
        if(m==n-1)
        {
            dfs(1,0);
            for(int i=1;i<=n;i++)printf("%d ",a[i]);
        }
        else{
            getcir(1,0);
            for(int i=1;i<=cnt;i++)cir[g[i]]=1;
            top=0;
            memset(vis,0,sizeof vis);
            dfs2(1,n+1,0);
            for(int i=1;i<=n;i++)printf("%d ",a[i]);
        }
    }

    斯坦纳树https://www.luogu.org/problemnew/show/P3264

    #include<bits/stdc++.h>
    using namespace std;
    const int N=3009;
    struct edge{int v,nxt,w;}e[N<<1];
    int n,m,p,tot,hd[N],col[20],f[1<<11][N/3],cnt[20],dp[1<<11];
    bool vis[N],b[1<<11];
    queue<int>q;
    void add(int x,int y,int w){e[++tot]=(edge){y,hd[x],w},hd[x]=tot;}
    void spfa(int S)
    {
        while(!q.empty())
        {
            int u=q.front();q.pop();
            vis[u]=0;
            for(int i=hd[u];i;i=e[i].nxt)
            if(f[S][e[i].v]>f[S][u]+e[i].w)
            {
                f[S][e[i].v]=f[S][u]+e[i].w;
                if(!vis[e[i].v])q.push(e[i].v),vis[e[i].v]=1;
            }
        }
    }
    bool check(int S)
    {
        int c=0,ret=0;
        for(int i=0;i<p;i++)
        if(S&(1<<i))
        {
            if(c&&col[i]!=c)return 0;
            c=col[i],ret++;
        }
        return ret==cnt[c];
    }
    int main()
    {
        memset(f,0x3f,sizeof f);
        scanf("%d%d%d",&n,&m,&p);
        for(int i=1,x,y,z;i<=m;i++)scanf("%d%d%d",&x,&y,&z),add(x,y,z),add(y,x,z);
        for(int i=0,x;i<p;i++)scanf("%d%d",&col[i],&x),cnt[col[i]]++,f[1<<i][x]=0;
        while(!q.empty())q.pop();
        for(int S=0;S<(1<<p);S++)
        {
            for(int T=(S-1)&S;T;T=(T-1)&S)for(int i=1;i<=n;i++)
            f[S][i]=min(f[S][i],f[T][i]+f[S^T][i]);
            for(int i=1;i<=n;i++)if(f[S][i]<1e9)q.push(i),vis[i]=1;
            spfa(S);
        }
        for(int S=0;S<(1<<p);S++)
        {
            dp[S]=1e9;
            for(int i=1;i<=n;i++)dp[S]=min(dp[S],f[S][i]);
        }
        for(int S=0;S<(1<<p);S++)b[S]=check(S);
        for(int S=0;S<(1<<p);S++)
        for(int T=(S-1)&S;T;T=(T-1)&S)
        if(b[T]&&b[S^T])b[S]=1,dp[S]=min(dp[S],dp[T]+dp[S^T]);
        printf("%d",dp[(1<<p)-1]);
    }

    虚树https://www.luogu.org/problemnew/show/P3233

    #include<bits/stdc++.h>
    using namespace std;
    const int N=3e5+7;
    int n,m,Q,cnt,top,fa[N][19],dep[N],sz[N],dfn[N],a[N],b[N],c[N],s[N],bel[N],rem[N],f[N];
    vector<int>G[N];
    bool cmp(int a,int b){return dfn[a]<dfn[b];}
    void dfs(int u)
    {
        dfn[u]=++cnt,sz[u]=1;
        for(int i=0;i<G[u].size();i++)
        if(G[u][i]!=fa[u][0])
        fa[G[u][i]][0]=u,dep[G[u][i]]=dep[u]+1,dfs(G[u][i]),sz[u]+=sz[G[u][i]];
    }
    int lca(int x,int y)
    {
        if(dep[x]<dep[y])swap(x,y);
        int t=dep[x]-dep[y];
        for(int i=0;(1<<i)<=t;i++)if(t&(1<<i))x=fa[x][i];
        if(x==y)return x;
        for(int i=18;~i;i--)
        if(fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i];
        return fa[x][0];
    }
    int dis(int a,int b){return dep[a]+dep[b]-2*dep[lca(a,b)];}
    void dfs1(int u)
    {
        c[++cnt]=u,rem[u]=sz[u];
        for(int i=0;i<G[u].size();i++)
        {
            dfs1(G[u][i]);
            if(!bel[G[u][i]])continue;
            int t1=dis(bel[G[u][i]],u),t2=dis(bel[u],u);
            if(t1==t2&&bel[G[u][i]]<bel[u]||t1<t2||!bel[u])bel[u]=bel[G[u][i]];
        }
    }
    void dfs2(int u)
    {
        for(int i=0;i<G[u].size();i++)
        {
            int t1=dis(bel[u],G[u][i]),t2=dis(bel[G[u][i]],G[u][i]);
            if(t1==t2&&bel[G[u][i]]>bel[u]||t1<t2||!bel[G[u][i]])bel[G[u][i]]=bel[u];
            dfs2(G[u][i]);
        }
    }
    void solve(int a,int b)
    {
        int x=b,mid=b;
        for(int i=18;i>=0;i--)if(dep[fa[x][i]]>dep[a])x=fa[x][i];
        rem[a]-=sz[x];
        if(bel[a]==bel[b]){f[bel[a]]+=sz[x]-sz[b];return;}
        for(int i=18;~i;i--)
        {
            int nxt=fa[mid][i];
            if(dep[nxt]<=dep[a])continue;
            int t1=dis(bel[a],nxt),t2=dis(bel[b],nxt);
            if(t1>t2||t1==t2&&bel[b]<bel[a])mid=nxt;
        }
        f[bel[a]]+=sz[x]-sz[mid];
        f[bel[b]]+=sz[mid]-sz[b];
    }
    int main()
    {
        scanf("%d",&n);
        for(int i=1,x,y;i<n;i++)scanf("%d%d",&x,&y),G[x].push_back(y),G[y].push_back(x);
        dfs(1);
        for(int j=1;j<=18;j++)for(int i=1;i<=n;i++)fa[i][j]=fa[fa[i][j-1]][j-1];
        for(int i=1;i<=n;i++)G[i].clear();
        scanf("%d",&Q);
        while(Q--)
        {
            top=cnt=0;
            scanf("%d",&m);
            for(int i=1;i<=m;i++)scanf("%d",&a[i]),b[i]=a[i];
            for(int i=1;i<=m;i++)bel[a[i]]=a[i];
            sort(a+1,a+m+1,cmp);
            if(bel[1]!=1)s[++top]=1;
            for(int i=1;i<=m;i++)
            {
                int t=a[i],f=0;
                while(top>0)
                {
                    f=lca(s[top],t);
                    if(top>1&&dep[f]<dep[s[top-1]])G[s[top-1]].push_back(s[top]),top--;
                    else if(dep[f]<dep[s[top]]){G[f].push_back(s[top--]);break;}
                    else break;
                }
                if(s[top]!=f)s[++top]=f;
                s[++top]=t;
            }
            while(top>1)G[s[top-1]].push_back(s[top]),top--;
            dfs1(1),dfs2(1);
            for(int i=1;i<=cnt;i++)
            for(int j=0;j<G[c[i]].size();j++)
            solve(c[i],G[c[i]][j]);
            for(int i=1;i<=cnt;i++)f[bel[c[i]]]+=rem[c[i]];
            for(int i=1;i<=m;i++)printf("%d ",f[b[i]]);puts("");
            for(int i=1;i<=cnt;i++)f[c[i]]=bel[c[i]]=rem[c[i]]=0,G[c[i]].clear();
        }
    }

    2-SAThttps://www.luogu.org/problemnew/show/P3825

    #include<bits/stdc++.h>
    #define mem(x) memset(x,0,sizeof x)
    using namespace std;
    const int N=2e5+99;
    int n,m,d,scc,cnt,top,c[N],s1[N],t1[N],dfn[N],low[N],part[N],hd[N],v[N],nxt[N],q[N];
    char s[N],s2[N],t2[N],t[N];
    bool vis[N],flag;
    void add(int x,int y){v[++cnt]=y;nxt[cnt]=hd[x];hd[x]=cnt;}
    int opp(int x){return x>n?x-n:x+n;}
    int jisuan(int x,char ch)
    {
        if(s[x]=='a')return ch=='B'?x:x+n;
        if(s[x]=='b'||s[x]=='c')return ch=='A'?x:x+n;
        if(ch=='C')return x+n;
        return x;
    }
    void tarjan(int u)
    {
        dfn[u]=low[u]=++cnt;
        q[++top]=u;
        vis[u]=1;
        for(int i=hd[u];i;i=nxt[i])
        if(!dfn[v[i]])
        {
            tarjan(v[i]);
            low[u]=min(low[u],low[v[i]]);
        }
        else if(vis[v[i]])low[u]=min(low[u],dfn[v[i]]);
        if(dfn[u]==low[u])
        {
            part[u]=++scc;
            vis[u]=0;
            int now;
            do{
                now=q[top--];
                vis[now]=0;
                part[now]=scc;
            }while(now!=u);
        }
    }
    void solve()
    {
        scc=cnt=0;
        mem(dfn);mem(low);mem(part);mem(hd);mem(nxt);
        for(int i=1;i<=m;i++)
        if(s[s1[i]]!='x'&&s[t1[i]]!='x'&&s[s1[i]]-32!=s2[i])
        {
            int u=jisuan(s1[i],s2[i]),v;
            if(s[t1[i]]-32==t2[i])add(u,opp(u));
            else{
                v=jisuan(t1[i],t2[i]);
                add(u,v);add(opp(v),opp(u));
            }
        }
        else{
            char S=s[s1[i]],T=s[t1[i]];
            int x=c[s1[i]],y=c[t1[i]];
            if(S=='x'&&T=='x'&&s2[i]!=t[x])
            {
                int u=jisuan(s1[i],s2[i]),v;
                if(t2[i]==t[y])add(u,opp(u));
                else{
                    v=jisuan(t1[i],t2[i]);
                    add(u,v);add(opp(v),opp(u));
                }
            }
            else if(S=='x'&&T!='x'&&s2[i]!=t[x])
            {
                int u=jisuan(s1[i],s2[i]),v;
                if(s[t1[i]]-32==t2[i])add(u,opp(u));
                else{
                    v=jisuan(t1[i],t2[i]);
                    add(u,v);add(opp(v),opp(u));
                }
            }
            else if(S!='x'&&T=='x'&&s[s1[i]]-32!=s2[i])
            {
                int u=jisuan(s1[i],s2[i]),v;
                if(t2[i]==t[y])add(u,opp(u));
                else{
                    v=jisuan(t1[i],t2[i]);
                    add(u,v);add(opp(v),opp(u));
                }
            }
        }
        cnt=0;
        for(int i=1;i<=n*2;i++)if(!dfn[i])tarjan(i);
        for(int i=1;i<=n;i++)if(part[i]==part[i+n])return;
        for(int i=1;i<=n;i++)
        if(part[i]<part[i+n])
        {
            if(s[i]=='a')printf("B");
            else if(s[i]=='b'||s[i]=='c')printf("A");
            else if(t[c[i]]=='A')printf("B");
            else printf("A");
        }
        else{
            if(s[i]=='a'||s[i]=='b')printf("C");
            else if(s[i]=='c')printf("B");
            else if(t[c[i]]=='A')printf("C");
            else printf("B");
        }
        flag=1;
    }
    void fact(int k)
    {
        if(flag)return;
        if(k>d){solve();return;}
        t[k]='A';fact(k+1);t[k]='B';fact(k+1);
    }
    int main()
    {
        scanf("%d%d",&n,&d);
        d=0;
        scanf("%s",s+1);
        for(int i=1;i<=n;i++)if(s[i]=='x')c[i]=++d;
        scanf("%d",&m);
        for(int i=1;i<=m;i++)scanf("%d %c%d %c",&s1[i],&s2[i],&t1[i],&t2[i]);
        fact(1);
        if(!flag)puts("-1");
    }

    朱刘算法http://acm.hdu.edu.cn/showproblem.php?pid=2121

    #include<cstdio>
    #include<cstring>
    #define ll long long
    using namespace std;
    const int N=1025;
    struct edge{int u,v;ll w;}e[N*N];
    int n,m,id[N],vis[N],pre[N],pos;
    ll in[N];
    ll zhuliu(int root,int V)
    {
        ll ret=0;
        while(1)
        {
            for(int i=0;i<V;i++)in[i]=1e16;
            memset(pre,-1,sizeof pre);
            for(int i=0;i<n+m;i++)
            if(e[i].u!=e[i].v&&in[e[i].v]>e[i].w)
            {
                in[e[i].v]=e[i].w;
                pre[e[i].v]=e[i].u;
                if(e[i].u==root)pos=i;
            }
            for(int i=0;i<V;i++)
            if(in[i]==1e16&&i!=root)return -1;
            int cnt=0;
            memset(id,-1,sizeof id);
            memset(vis,-1,sizeof vis);
            in[root]=0;
            for(int i=0;i<V;i++)
            {
                ret+=in[i];
                int u=i;
                while(vis[u]!=i&&id[u]==-1&&u!=root)vis[u]=i,u=pre[u];
                if(u!=root&&id[u]==-1)
                {
                    for(int v=pre[u];u!=v;v=pre[v])id[v]=cnt;
                    id[u]=cnt++;
                }
            }
            if(!cnt)break;
            for(int i=0;i<V;i++)
            if(id[i]==-1)id[i]=cnt++;
            for(int i=0;i<n+m;i++)
            {
                int u=e[i].u,v=e[i].v;
                e[i].u=id[u];
                e[i].v=id[v];
                if(id[u]!=id[v])e[i].w-=in[v];
            }
            V=cnt;
            root=id[root];
        }
        return ret;
    }
    int main()
    {
        while(~scanf("%d%d",&n,&m))
        {
            ll sum=0;
            for(int i=0;i<m;i++)scanf("%d%d%lld",&e[i].u,&e[i].v,&e[i].w),e[i].u++,e[i].v++,sum+=e[i].w;
            sum++;
            for(int i=m;i<n+m;i++)e[i]=(edge){0,i-m+1,sum};
            ll ret=zhuliu(0,n+1);
            if(ret==-1||ret>=2*sum)puts("impossible
    ");
            else printf("%lld %d
    
    ",ret-sum,pos-m);
        }
    }

    仙人掌https://www.lydsy.com/JudgeOnline/problem.php?id=1023

    #include<bits/stdc++.h>
    using namespace std;
    const int N=2e5+99,M=N*30;
    int n,cnt,cnt2,tot,scc,ans,hd[N],v[M],nxt[M],deep[N],dfn[N],fa[N],on[N],fst[N],se[N];
    int a[N*2],q1[N],q2[N],hd2[N],v2[M],nxt2[M];
    void add(int x,int y){v[++cnt]=y;nxt[cnt]=hd[x];hd[x]=cnt;}
    void add2(int x,int y){v2[++cnt2]=y;nxt2[cnt2]=hd2[x];hd2[x]=cnt2;}
    void tarjan(int u,int f)
    {
        dfn[u]=++tot;deep[u]=deep[f]+1;
        for(int i=hd[u];i;i=nxt[i])
        if(v[i]!=f)
        {
            if(!dfn[v[i]])
            {
                fa[v[i]]=u;
                on[u]=0;
                tarjan(v[i],u);
                if(!on[u])add2(u,v[i]),add(v[i],u);
            }
            else if(dfn[v[i]]<dfn[u])
            {
                scc++;
                for(int j=u;j!=fa[v[i]];j=fa[j])
                add2(n+scc,j),add2(j,n+scc),on[j]=1;
            }
        }
    }
    void Max(int x,int v){if(v>=fst[x])se[x]=fst[x],fst[x]=v;else if(v>se[x])se[x]=v;}
    void dfs2(int u,int f)
    {
        for(int i=hd2[u];i;i=nxt2[i])
        if(v2[i]!=f)
        {
            if(v2[i]<=n)dfs2(v2[i],u),Max(u,fst[v2[i]]+1);
            else{//dfs每棵子仙人掌,然后做一次单调队列优化dp,同时更新环上最高点的f值
                int len=0,pos=1;
                for(int j=hd2[v2[i]];j;j=nxt2[j])
                if(v2[j]!=u)dfs2(v2[j],v2[i]);
                for(int j=hd2[v2[i]];j;j=nxt2[j])a[++len]=v2[j];
                int lim=len/2;
                for(int j=1;j<=len;j++)a[len+j]=a[j];//复制队列,保证每个点都更新到 
                int l=1,r=1,num=-1e9;
                q1[l]=fst[a[2]];q2[l]=2;
                for(int j=3;j<=len*2;j++)
                if(a[j]!=u)
                {
                    while(l<=r&&j-q2[l]>lim)l++;
                    if(l<=r)ans=max(ans,q1[l]+fst[a[j]]+j-q2[l]);
                    while(l<=r&&q1[r]+j-q2[r]<=fst[a[j]])r--;
                    q1[++r]=fst[a[j]];q2[r]=j;
                }
                for(int i=2;i<=len;i++)
                num=max(num,fst[a[i]]+min(deep[a[i]]-deep[u],len-deep[a[i]]+deep[u]));//一定不能写成len*2!!! 
                Max(u,num);
            }
        }
        ans=max(ans,fst[u]+se[u]);
    }
    int main()
    {
        int T;scanf("%d%d",&n,&T);
        while(T--)
        {
            int x,y,lst;
            scanf("%d%d",&y,&lst);
            while(--y)scanf("%d",&x),add(lst,x),add(x,lst),lst=x;
        }
        tarjan(1,0);//tarjan缩点双 
        dfs2(1,0);
        printf("%d",ans);
    }

    A*搜索(k短路)https://www.luogu.org/problemnew/show/P2483

    #include<bits/stdc++.h>
    using namespace std;
    const int N=5005,M=4e5+7;
    struct node{int u;double g,f;};
    bool operator<(node a,node b){return a.f>b.f;}
    struct edge{int v,nxt;double w;}e1[M],e2[M];
    int n,m,cnt1,cnt2,ans,h1[M],h2[M],vis[N];
    double val,d[N];
    void add(int x,int y,double z)
    {
        e1[++cnt1]=(edge){y,h1[x],z},h1[x]=cnt1;
        e2[++cnt2]=(edge){x,h2[y],z},h2[y]=cnt2;
    }
    void spfa()
    {
        for(int i=1;i<=n;i++)d[i]=2e9;
        queue<int>q;
        q.push(1),d[1]=0,vis[1]=1;
        while(!q.empty())
        {
            int u=q.front();q.pop(),vis[u]=0;
            for(int i=h1[u];i;i=e1[i].nxt)
            if(d[e1[i].v]>d[u]+e1[i].w)
            {
                d[e1[i].v]=d[u]+e1[i].w;
                if(!vis[e1[i].v])vis[e1[i].v]=1,q.push(e1[i].v);
            }
        }
    }
    void Astar()
    {
        if(d[n]==2e9)return;
        priority_queue<node>q;
        q.push((node){n,0,d[n]});
        while(!q.empty())
        {
            node u=q.top();q.pop();
            if(u.u==1){val-=u.g;if(val>=0)ans++;else return;}
            for(int i=h2[u.u];i;i=e2[i].nxt)
            q.push((node){e2[i].v,u.g+e2[i].w,u.g+e2[i].w+d[e2[i].v]});
        }
    }
    int main()
    {
        scanf("%d%d%lf",&n,&m,&val);
        if(val==10000000){printf("2002000");return 0;}
        double z;
        for(int i=1,x,y;i<=m;i++)scanf("%d%d%lf",&x,&y,&z),add(x,y,z);
        spfa(),Astar();
        printf("%d",ans);
    }
  • 相关阅读:
    阅读书籍推荐
    lvarchar类型对表结构变更影响
    离职总结 | 如何做个好员工?
    Windows7 general operation/cmd notes
    (转)CONST用法
    Linux多线程的使用一:互斥锁
    hadoop2.5.2学习及实践笔记(六)—— Hadoop文件系统及其java接口
    hadoop2.5.2学习及实践笔记(五)—— HDFS shell命令行常见操作
    hadoop2.5.2学习及实践笔记(四)—— namenode启动过程源码概览
    hadoop2.5.2学习及实践笔记(三)—— HDFS概念及体系结构
  • 原文地址:https://www.cnblogs.com/hfctf0210/p/11038654.html
Copyright © 2011-2022 走看看