树上问题&图论模板整理

去除过水的模板,包括但不限于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);
}
原文地址:https://www.cnblogs.com/hfctf0210/p/11038654.html