zoukankan      html  css  js  c++  java
  • 图论

    spfa

      邻接矩阵

    int dist[maxn],mp[maxn][maxn];
    int visit[maxn];
    void spfa()     //SPFA算法
    {
        int i, now;
        memset(visit, false, sizeof(visit));
        for(i = 1; i <= n; i++) dist[i] = inf;
        dist[1] = 0;
        queue<int> Q;
        Q.push(1);
        visit[1] = true;
        while(!Q.empty())
        {
            now = Q.front();
            Q.pop();
            visit[now] = false;
            for(i = 1; i <= n; i++)
            {
                if(dist[i] > dist[now] + mp[now][i])
                {
                    dist[i] = dist[now] + mp[now][i];
                    if(visit[i] == 0)
                    {
                        Q.push(i);
                        visit[i] = true;
                    }
                }
            }
        }
    }
    View Code

      邻接表

    int n,m,ans;
    int head[MAXN];
    int begin1,end1;
    int dis[MAXN],vis[MAXN];
    
    struct node
    {
        int u,v,w;
        int next;
    }edge[MAXN];
    void init()
    {
        ans=0;
        memset(head,-1,sizeof(head));
    }
    void add(int u,int v,int w)
    {
        edge[ans].u=u;
        edge[ans].v=v;
        edge[ans].w=w;
        edge[ans].next=head[u]; // next标记以u为起点的下一条边
        head[u]=ans++; // head标记这个点是哪条边的起点,更新head
    }
    
    void SPFA(int begin1)
    {
        int i,j;
        queue<int>q;
        for(int i=0;i<n;i++) dis[i]=INF;
        memset(vis,0,sizeof(vis));
        dis[begin1]=0,vis[begin1]=1;
    
        q.push(begin1);
        while(!q.empty()){
            int u=q.front();
            q.pop();
            vis[u]=0;
            for(i=head[u];i!=-1;i=edge[i].next){
                int top=edge[i].v;
                if(dis[top]>dis[u]+edge[i].w){
                    dis[top]=dis[u]+edge[i].w;
                    if(!vis[top]){
                        vis[top]=1;
                        q.push(top);
                    }
                }
            }
        }
        if(dis[end1]==INF) printf("-1
    ");
        else printf("%d
    ",dis[end1]);
    }
    View Code

    Dijkstra

    const int INF = 0x3f3f3f3f;
    int dis[maxn],n;
    struct node{
        int x,d;
        node(){}
        node(int a,int b){x=a;d=b;}
        bool operator < (const node & a) const
        {
            if(d==a.d) return x<a.x;
            else return d > a.d;
        }
    };
    vector<node> eg[maxn];
    
    void init()
    {
        for(int i=0;i<=n;i++)
            eg[i].clear();
    }
    
    void Dijkstra(int s)
    {
        memset(dis,INF,sizeof(dis));
        dis[s]=0;
        priority_queue<node> q;
        q.push(node(s,dis[s]));
        while(!q.empty()){
            node x=q.top();
            q.pop();
            for(int i=0;i<eg[x.x].size();i++){
                node y=eg[x.x][i];
                if(dis[y.x]>x.d+y.d){
                    dis[y.x]=x.d+y.d;
                    q.push(node(y.x,dis[y.x]));
                }
            }
        }
    }
    View Code

     邻接表

    const int maxm=200500;
    const int maxn=100500;
    inline int read()
    {
        int x=0;char ch=getchar();
        while (ch<'0'||ch>'9') ch=getchar();
        while (ch<='9'&&ch>='0'){x=x*10+ch-'0';ch=getchar();}
        return x;
    }
    struct edge{
        int u,v,a,b,next;
    }e[maxm];
    int edgenum,head[maxn];
    void addedge(int u,int v,int a,int b){
        e[edgenum].u=u;
        e[edgenum].v=v;
        e[edgenum].a=a;
        e[edgenum].b=b;
        e[edgenum].next=head[u];
        head[u]=edgenum++;
    }
    
    struct Node{
        int id;
        LL d;
        Node(int id, LL d):id(id),d(d){}
        bool operator < (const Node &A)const{
            return d > A.d;
        }
    };
    
    LL d[maxn];
    bool vis[maxn];
    int dijkstra(int S,int T){
        memset(d,0x3f,sizeof(d));
        memset(vis,0,sizeof(vis));
        priority_queue<Node> que;
        que.push(Node(S,1));
        d[S]=1;
        while(!que.empty()){
            Node tp1=que.top();
            que.pop();
            int tp=tp1.id;
            if(tp==T){
                for(int i=1;;i++){
                    if((1LL<<i)>tp1.d)return i-1;
                }
            }
            if(vis[tp])continue;
            vis[tp]=1;
            for(int i=head[tp];i!=-1;i=e[i].next){
                if(vis[e[i].v])continue;
                if(((e[i].a+tp1.d)/(tp1.d))>=(1LL<<e[i].b)&&e[i].a+tp1.d<d[e[i].v]){
                    d[e[i].v]=e[i].a+tp1.d;
                    que.push(Node(e[i].v,d[e[i].v]));
                }
            }
        }
        return -1;
    }
    View Code

     前向星

    int cnt;
    struct node
    {
        int from,to,val,next;
    }edge[maxm<<1];
    int head[maxm];
    LL dis[maxn];
    int vis[maxn];
    struct Node
    {
        int val,id;
        bool operator <(const Node &b)const
        {
            if(val==b.val)return id<b.id;
            return val>b.val;
        }
    };
    void init()
    {
        memset(head,-1,sizeof(head));
        cnt=1;
    }
    void addedge(int from,int to,int val)
    {
        edge[cnt].from=from;
        edge[cnt].to=to;
        edge[cnt].val=val;
        edge[cnt].next=head[from];
        head[from]=cnt++;
    }
    
    void dijkstra(int s,int e)
    {
        memset(vis,0,sizeof(vis));
        memset(dis,0x7f,sizeof(dis));
        Node now;
        priority_queue<Node>q;
        while(q.size())q.pop();
        now.val=0,now.id=s;
        dis[s]=0;
        q.push(now);
        while(!q.empty()){
            Node u=q.top();
            q.pop();
            if(vis[u.id])continue;
            vis[u.id]=1;
            for(int i=head[u.id];i!=-1;i=edge[i].next){
                int to=edge[i].to;
                if(dis[u.id]+edge[i].val<dis[to]){
                    dis[to]=dis[u.id]+edge[i].val;
                    Node pus;
                    pus.id=to,pus.val=dis[to];
                    q.push(pus);
                }
            }
        }
        return ;
    }
    View Code

     二维dijkstra

    struct node
    {
        int next,to,val;
    }edge[100005];
    int head[10005],cnt;
    struct Node
    {
        int to,val,sum;
        friend bool operator<(Node a,Node b){return a.val>b.val;}
    };
    void addedge(int u,int v,int w)
    {
        edge[++cnt].next=head[u];
        edge[cnt].to=v;
        edge[cnt].val=w;
        head[u]=cnt;
    }
    void add(int u,int v,int w)
    {
        addedge(u,v,w);
        addedge(v,u,w);
    }
    void init()
    {
        cnt=0;
        memset(head,-1,sizeof(head));
    }
    int dis[10005][25],vis[10005][25];
    int k;
    void dijsktra(int s)
    {
        priority_queue<Node>que;
        memset(dis,127/3,sizeof(dis));
        dis[s][0]=0;
        que.push((Node){s,0,0});
        while(!que.empty()){
            Node x=que.top();que.pop();
            if(vis[x.to][x.sum])continue;
            vis[x.to][x.sum]=1;
            for(int i=head[x.to];i!=-1;i=edge[i].next){
                int y=edge[i].to;
                if(dis[y][x.sum+1]>dis[x.to][x.sum]&&x.sum+1<=k){
                    dis[y][x.sum+1]=dis[x.to][x.sum];
                    que.push((Node){y,dis[y][x.sum+1],x.sum+1});
                }
                if(dis[y][x.sum]>dis[x.to][x.sum]+edge[i].val){
                    dis[y][x.sum]=dis[x.to][x.sum]+edge[i].val;
                    que.push((Node){y,dis[y][x.sum],x.sum});
                }
            }
        }
        return ;
    }
    View Code

     K短路

    int s,t;
    int tot;
    int retot;
    struct Edge{
        int to,w;
        int next1;
    }edge[maxe],redge[maxe];
    //f = g + h
    ///先跑spfa,在跑Astar,s,t为起点终点
    struct Node{
        int v;
        int f,h,g;
        bool operator <(const Node &a)const
        {
            if(f==a.f)return g>a.g;
            return f>a.f;
        }
    };
    int dis[maxn],head[maxe],rehead[maxe],vis[maxn];
    void init()
    {
        tot=0 ;
        retot=0;
        memset(head,-1,sizeof(head));
        memset(rehead,-1,sizeof(rehead));
    }
    void addedge(int u,int v,int c){
        edge[tot].to=v;
        edge[tot].w=c;
        edge[tot].next1=head[u];
        head[u]=tot++;
    
        redge[retot].to=u;
        redge[retot].w=c;
        redge[retot].next1=rehead[v];
        rehead[v]=retot++;
    }
    void spfa(){
        for(int i=1;i<=n;i++)dis[i]=INF;
        dis[t]=0;
        queue<int>Q;
        Q.push(t);
        while(!Q.empty()){
            int u=Q.front();
            Q.pop();
            for(int i=rehead[u];~i;i=redge[i].next1){
                int v=redge[i].to;
                int w=redge[i].w;
                if(dis[v]>dis[u]+w){
                    dis[v]=dis[u]+w;
                    Q.push(v);
                }
            }
        }
    }
    
    int Astar(int st){
        Node a;
        a.v=st;
        a.g=0;
        a.h=dis[st];
        a.f=a.g+a.h;
        memset(vis,0,sizeof(vis));
        if(dis[s]==INF) return -1;
        if(s==t)k++;
        priority_queue<Node>que;
        que.push(a);
        while(!que.empty()){
            Node tmp=que.top();
            que.pop();
            int v=tmp.v;
            vis[v]++;
            if(vis[t]==k) return tmp.g;
            for(int i=head[v];~i;i=edge[i].next1 ){
                Node p;
                p.v=edge[i].to;
                p.h=dis[edge[i].to];
                p.g=tmp.g + edge[i].w;
                p.f=p.g + p.h;
                que.push(p);
            }
        }
        return -1;
    }
    View Code

    最小生成树

      邻接表(kruskal) 

    int fa[maxn],sum,len;
    struct edge
    {
        int u,v,w;
        bool operator <(const edge &b)const{
            return w<b.w;
        }
    }g[maxn];
    void init()
    {
        sum=0;len=0;
        for(int i=0;i<=n;i++)fa[i]=i;
    }
    int Find(int x)
    {
        return fa[x]==x?x:fa[x]=Find(fa[x]);
    }
    void addedge(int u,int v,int w)
    {
        g[len].u=u;
        g[len].v=v;
        g[len++].w=w;
    }
    void kruskal()
    {
        int cot=0;
        sort(g,g+len);
        for(int i=0;i<len;i++){
            int t1=Find(g[i].u);
            int t2=Find(g[i].v);
            if(t1!=t2){
                fa[t2]=t1;
                cot++;
                sum=sum+g[i].w;///return sum
            }
            if(cot==n-1) break;
        }
    }
    View Code

     最小树形图

      朱刘算法(无左偏树优化)

    const int INF=0x7f7f7f7f;
    const int maxn=1005;
    struct Node
    {
        int u,v;
        LL w;
    }edge[maxn*maxn];
    int pre[maxn],id[maxn],vis[maxn],n,m,pos;
    long long in[maxn];
    long long Directed_MST(int root,int V,int E)
    {///点和边都是从0开始的
        long long ret=0;
        while(true){
            for(int i=0;i<V;i++)in[i]=INF;
            for(int i=0;i<E;i++){
                int u=edge[i].u;
                int v=edge[i].v;
                if(edge[i].w<in[v]&&u!=v){
                    pre[v]=u;
                    in[v]=edge[i].w;
                    if(u==root)pos = i;
                }
            }
            for(int i=0;i<V;i++){
                if(i==root)continue;
                if(in[i]==INF)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 v=i;
                while(vis[v]!=i&&id[v]==-1&&v!=root){
                    vis[v]=i;
                    v=pre[v];
                }
                if(v!=root&&id[v]==-1){
                    for(int u=pre[v];u!=v;u=pre[u])id[u]=cnt;
                    id[v]=cnt++;
                }
            }
            if(cnt==0)break;
            for(int i=0;i<V;i++)
                if(id[i]==-1)id[i] = cnt++;
                for(int i=0;i<E;i++){
                    int u=edge[i].u;
                    int v=edge[i].v;
                    edge[i].u=id[u];
                    edge[i].v=id[v];
                    if(id[u]!=id[v])edge[i].w-=in[v];
                }
                V=cnt;root=id[root];
        }
        return ret;
    }
    View Code

    割点tarjan

    const int maxn=110;
    int num[maxn],low[maxn],head[maxn],vis[maxn];///head为头,初始化为-1,Tarjan(root,-1)
    bool cut[maxn];///cut代表是不是割点
    int res,n,cnt,root;
    
    struct Edge{
        int to,next;
    }edge[maxn<<1];
    
    void init()
    {
        memset(head,-1,sizeof(head));
        memset(num,0,sizeof(num));
        memset(low,0,sizeof(low));
        memset(vis,0,sizeof(vis));
        memset(cut,0,sizeof(cut));
        cnt=0;res=0;
    }
    void addedge(int u,int v){
        edge[cnt].to=v;
        edge[cnt].next=head[u];
        head[u]=cnt++;
    }
    
    void Tarjan(int u,int fa){
        int son=0;
        vis[u]=1;
        num[u]=low[u]=++res;
        for(int i=head[u];i!=-1;i=edge[i].next){
            int v=edge[i].to;
            if(vis[v]==1 && v!=fa){
                low[u]=min(low[u],num[v]);
            }
            if(vis[v]==0){
                Tarjan(v,u);
                son++;
                low[u]=min(low[u],low[v]);
                if((u==root && son>1) || (u!=root && num[u]<=low[v]))
                    cut[u]=1;
            }
        }
        vis[u]=2;
    }
    View Code
    int sum, dfn[maxe], low[maxe], vis[maxe], stk[maxe], top, col[maxe];
    void tarjan(int x)
    {
      dfn[x] = low[x] = ++ sum;
      vis[x] = 1;
      stk[++top] =x;
      for(int i = head1[x]; i; i = nxt[i]) {
        if(!vis[to[i]]) {
          tarjan(to[i]);
          low[x] = min(low[x], low[to[i]]);
        }
        else if(vis[to[i]] == 1) {
          low[x] = min(low[x], dfn[to[i]]);
        }
      }
      if(dfn[x] == low[x]) {
        do {
          vis[stk[top]] = 2;
          col[stk[top]] = x;
        }
        while(stk[top--] != x);
      }
    }
    View Code

    最大流

    struct Edge{
        int next,to,f;
    };
    struct Dinic
    {
        int s,t;
        Edge e[1000010];
        int cnt=2,head[1000010]={0};
        int dis[1000010]={0};
        Dinic (){}
        void init(int _s,int _t)
        {
            cnt=2;
            s=_s,t=_t;
            memset(head,0,sizeof(head));
        }
        void addedge(int u,int v,int f)
        {
            e[cnt]={head[u],v,f};
            head[u]=cnt++;
            e[cnt]={head[v],u,0};
            head[v]=cnt++;
        }
        bool bfs()
        {
            memset(dis,0,sizeof(dis));
            dis[s]=1;
            queue<int> q;
            q.push(s);
            while(!q.empty())
            {
                int u=q.front();
                q.pop();
                for(int i=head[u];i;i=e[i].next)
                {
                    int v=e[i].to;
                    if(!dis[v]&&e[i].f>0)
                    {
                        dis[v]=dis[u]+1;
                        q.push(v);
                    }
                }
            }
            return dis[t]!=0;
        }
    
        int dfs(int u,int flow)
        {
            if(u==t||flow==0) return flow;
            int flow_sum=0;
            for(int i=head[u];i;i=e[i].next)
            {
                int v=e[i].to,f=e[i].f;
                if(dis[v]!=dis[u]+1||f==0) continue;
                int temp=dfs(v,min(flow-flow_sum,f));
                e[i].f-=temp;
                e[i^1].f+=temp;
                flow_sum+=temp;
                if(flow_sum>=flow) break;
            }
            if(!flow_sum) dis[u]=-1;
            return flow_sum;
        }
    
        int maxflow()
        {
            int ans=0;
            while(bfs())
            {
                while(int temp=dfs(s,0x7fffffff))
                    ans+=temp;
            }
            return ans;
        }
    }DC;
    View Code

    最小费用最大流

    struct Min_cost_flow
    {
        int S,T,ans=0;
        int vis[100010],vis2[100010];
        int d[100010],head[100010],to[100010],nextt[100010],w[100010],cost[100010];
        int tot = 2;
        int inf=0x7fffffff;
        void init(int _s,int _t)
        {
            S=_s;T=_t;
            memset(head,0,sizeof(head));
            ans=0;tot=2;
        }
        void add(int u,int v,int cap,int co)
        {
            cost[tot]=co;
            w[tot]=cap;
            to[tot]=v;
            nextt[tot]=head[u];
            head[u]=tot++;
            cost[tot] = -co;
            w[tot]=0;
            to[tot]=u;
            nextt[tot]=head[v];
            head[v]=tot++;
        }
        bool spfa()
        {
            memset(vis,0,sizeof(vis));
            memset(vis2,0,sizeof(vis2));
            for(int i = 1;i<=T;i++)d[i]=inf;
            queue<int> q;
            q.push(S);
            d[S]=0;
            vis[S]=1;
            while(!q.empty())
            {
                int u=q.front();
                q.pop();
                vis[u]=0;
                for(int i = head[u];i;i=nextt[i])
                {
                    int v = to[i];
                    if(w[i] && d[v]>d[u]+cost[i])
                    {
                        d[v]=d[u]+cost[i];
                        if(!vis[v])
                        {
                            vis[v]=1;
                            q.push(v);
                        }
                    }
                }
            }
            return d[T]<inf;
        }
        int dfs(int u,int f)
        {
            if(u==T)
            {
                ans+=d[u] * f;
                return f;
            }
            int res=0;
            vis2[u]=1;
            for(int i=head[u];i;i=nextt[i])
            {
                int v = to[i];
                if (w[i] && !vis2[v] && d[v]==d[u]+cost[i])
                {
                    int temp=dfs(v,min(f-res,w[i]));
                    w[i] -= temp;
                    w[i^1] += temp;
                    res += temp;
                    if(res == f)return res;
                }
            }
            return res;
        }
        int MCMF()
        {
            while(spfa())dfs(S,inf);
            return ans;
        }
    }mcmf;
    View Code

      浮点数最小费用最大流,只是加了eps,不然会T

    const double eps=1e-8;
    struct Min_cost_flow
    {
        int S,T;
        double ans=0;
        int vis[100010],vis2[100010];
        int head[100010],to[100010],nextt[100010],w[100010];
        double d[100010],cost[100010];
        int tot = 2;
        double inf=0x7fffffff;
        void init(int _s,int _t)
        {
            S=_s;T=_t;
            memset(head,0,sizeof(head));
            ans=0;tot=2;
        }
        void add(int u,int v,int cap,double co)
        {
            cost[tot]=co;
            w[tot]=cap;
            to[tot]=v;
            nextt[tot]=head[u];
            head[u]=tot++;
            cost[tot] = -co;
            w[tot]=0;
            to[tot]=u;
            nextt[tot]=head[v];
            head[v]=tot++;
        }
        bool spfa()
        {
            memset(vis,0,sizeof(vis));
            memset(vis2,0,sizeof(vis2));
            for(int i = 1;i<=T;i++)d[i]=inf;
            queue<int> q;
            q.push(S);
            d[S]=0;
            vis[S]=1;
            while(!q.empty())
            {
                int u=q.front();
                q.pop();
                vis[u]=0;
                for(int i = head[u];i;i=nextt[i])
                {
                    int v = to[i];
                    if(w[i] && d[v]>d[u]+cost[i]+eps)
                    {
                        d[v]=d[u]+cost[i];
                        if(!vis[v])
                        {
                            vis[v]=1;
                            q.push(v);
                        }
                    }
                }
            }
            return d[T]<inf;
        }
        int dfs(int u,int f)
        {
            if(u==T)
            {
                ans+=d[u] * f;
                return f;
            }
            int res=0;
            vis2[u]=1;
            for(int i=head[u];i;i=nextt[i])
            {
                int v = to[i];
                if (w[i] && !vis2[v] && d[v]==d[u]+cost[i])
                {
                    int temp=dfs(v,min(f-res,w[i]));
                    w[i] -= temp;
                    w[i^1] += temp;
                    res += temp;
                    if(res == f)return res;
                }
            }
            return res;
        }
        double MCMF()
        {
            while(spfa())dfs(S,inf);
            return ans;
        }
    }mcmf;
    View Code

      带返回流量的(好像有问题)

    struct Edge
    {
        int to,next,cap,flow,cost;
    }edge[maxm];
    int head[maxn],tol;
    int pre[maxn],dis[maxn];
    bool vis[maxn];
    int N;//节点总个数,节点编号从0~N-1
    void init(int n)
    {//0==S N-1==T
        N = n;
        tol = 0;
        memset(head,-1,sizeof(head));
    }
    void addedge(int u,int v,int cap,int cost)
    {
        edge[tol].to = v;
        edge[tol].cap = cap;
        edge[tol].cost = cost;
        edge[tol].flow = 0;
        edge[tol].next = head[u];
        head[u] = tol++;
        edge[tol].to = u;
        edge[tol].cap = 0;
        edge[tol].cost = -cost;
        edge[tol].flow = 0;
        edge[tol].next = head[v];
        head[v] = tol++;
    }
    bool spfa(int s,int t)
    {
        queue<int>q;
        for(int i = 0;i < N;i++)
        {
            dis[i] = INF;
            vis[i] = false;
            pre[i] = -1;
        }
        dis[s] = 0;
        vis[s] = true;
        q.push(s);
        while(!q.empty())
        {
            int u = q.front();
            q.pop();
            vis[u] = false;
            for(int i = head[u]; i != -1;i = edge[i].next)
            {
                int v = edge[i].to;
                if(edge[i].cap > edge[i].flow &&
                   dis[v] > dis[u] + edge[i].cost )
                {
                    dis[v] = dis[u] + edge[i].cost;
                    pre[v] = i;
                    if(!vis[v])
                    {
                        vis[v] = true;
                        q.push(v);
                    }
                }
            }
        }
        if(pre[t] == -1)return false;
        else return true;
    }
    //返回的是最大流,cost存的是最小费用
    int minCostMaxflow(int s,int t,int &cost)
    {
        int flow = 0;
        cost = 0;
        while(spfa(s,t)){
            int Min = INF;
            for(int i = pre[t];i != -1;i = pre[edge[i^1].to]){
                if(Min > edge[i].cap - edge[i].flow)
                    Min = edge[i].cap - edge[i].flow;
            }
            for(int i = pre[t];i != -1;i = pre[edge[i^1].to]){
                edge[i].flow += Min;
                edge[i^1].flow -= Min;
                cost += edge[i].cost * Min;
            }
            flow += Min;
        }
        return flow;
    }
    View Code

    无向图最小割

    struct Stoer_Wagner
    {
        int n,g[maxn][maxn],b[maxn],dis[maxn];
        void init(int nn,int w[maxn][maxn]){
            int i,j;
            n=nn;
            for(i=1;i<=n;i++){
                for(j=1;j<=n;j++){
                    g[i][j]=w[i][j];
                }
            }
        }
        int Min_Cut_Phase(int ph,int &x,int &y){
            int i,j,t;
            b[t=1]=ph;
            for(i=1;i<=n;++i)
                if(b[i]!=ph)dis[i]=g[1][i];
            for(i=1;i<n;++i){
                x=t;
                for(t=0,j=1;j<=n;++j)
                    if(b[j]!=ph && (!t||dis[j]>dis[t]))t=j;
                b[t]=ph;
                for(j=1;j<=n;++j)
                    if(b[j]!=ph)dis[j]+=g[t][j];
            }
            return y=t,dis[t];
        }
        void Merge(int x,int y){
            int i;
            if(x>y)swap(x,y);
            for(i=1;i<=n;++i)
                if(i!=x&&i!=y)
                    g[i][x]+=g[i][y],g[x][i]+=g[i][y];
            if(y==n)return ;
            for(i=1;i<n;++i)if(i!=y){
                swap(g[i][y],g[i][n]);
                swap(g[y][i],g[n][i]);
            }
        }
        int Min_Cut(){
            int i,ret=0x3fffffff,x,y;
            memset(b,0,sizeof(b));
            for(i=1;n>1;++i,--n){
                ret=min(ret,Min_Cut_Phase(i,x,y));
                Merge(x,y);
            }
            return ret;
        }
    }SW;
    View Code

    二分图

    有关系为1没关系为0

    int mp[maxn][maxn];
    int book[maxn],vis[maxn],sum;
    bool dfs(int x)
    {
        for(int i=1;i<=m;i++)
        {
            if(mp[x][i]&&!vis[i]){
                vis[i]=1;
                if(book[i]==0||dfs(book[i])){
                    book[i]=x;
                    return 1;
                }
            }
        }
        return 0;
    }
    int solve()
    {
        int sum=0;
        memset(book,0,sizeof(book));
        for(int i=1; i<=n; i++){
            memset(vis,0,sizeof(vis));
            if(dfs(i)) sum++;
        }
        return sum;
    }
    View Code

    倍增LCA(附带扩栈指令)

    int n,m,s,num;
    int f[maxn][30],head[maxn],dep[maxn];
    bool vis[maxn];
    LL val[maxn][60];
    struct node
    {
        int next,to;
    }e[maxn<<1];
    inline void add(int from,int to)
    {
        e[++num].next=head[from];
        e[num].to=to;
        head[from]=num;
    }
    inline void dfs(int x,int d,int pre)
    {
        vis[x]=1;dep[x]=d;
    
        for(int i=head[x];i;i=e[i].next)
        {
            int to=e[i].to;
            if(!vis[to])
            {
                f[to][0]=x;
                dfs(to,d+1,x);
            }
        }
    }
    inline int lca(int a,int b)
    {
        if(dep[a]<dep[b]){int t=a;a=b;b=t;}
        int d=dep[a]-dep[b];
        for(int i=20;i>=0;i--)
        if(d&(1<<i)) a=f[a][i];
        if(a==b) return a;
        for(int i=20;i>=0;i--)
        if(f[a][i]!=f[b][i])
        {
            a=f[a][i];
            b=f[b][i];
        }
        return f[a][0];
    }
    
    int main()
    {
        n=read();
        for(int i=1;i<n;i++){
            int u=read(),v=read();
            add(u,v);
            add(v,u);
        }
        dfs(s,1,0);//s是rt
        for(int j=1;j<=20;j++)
            for(int i=1;i<=n;i++)
                f[i][j]=f[f[i][j-1]][j-1];
        return 0;
    }
    View Code

    最小生成树计数

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    const int N=107;
    const int M=1007;
    const int MOD=31011;
    LL n,m,ans;
    vector<int>gra[N];
    struct edge{
        int u,v,w;
    }e[M];
    int cmp(edge a,edge b){
        return a.w<b.w;
    }
    LL mat[N][N],g[N][N];
    LL fa[N],ka[N],vis[N];
    LL det(LL c[][N],LL n){
        LL i,j,k,t,ret=1;
        for(i=0;i<n;i++)
            for(j=0;j<n;j++) c[i][j]%=MOD;
        for(i=0; i<n; i++){
            for(j=i+1; j<n; j++){
                while(c[j][i]){
                    t=c[i][i]/c[j][i];
                    for(k=i; k<n; k++)
                        c[i][k]=(c[i][k]-c[j][k]*t)%MOD;
                    swap(c[i],c[j]);
                    ret=-ret;
                }
            }
            if(c[i][i]==0)return 0L;
            ret=ret*c[i][i]%MOD;
        }
        return (ret+MOD)%MOD;
    }
    LL Find(LL a,LL f[]){
        return f[a]==a?a:Find(f[a],f);
    }
    void matrix_tree(){///对当前长度的边连接的每个联通块计算生成树个数
        for(int i=0;i<n;i++)if(vis[i]){///当前长度的边连接了i节点
            gra[Find(i,ka)].push_back(i);///将i节点压入所属的联通块
            vis[i]=0;///一边清空vis数组
        }
        for(int i=0;i<n;i++){
            if(gra[i].size()>1){///联通块的点数为1时生成树数量是1
                memset(mat,0,sizeof mat);///清空矩阵
                int len=gra[i].size();
                for(int j=0;j<len;j++){
                    for(int k=j+1;k<len;k++){///构造这个联通块的矩阵(有重边)
                        int u=gra[i][j],v=gra[i][k];
                        if(g[u][v]){
                            mat[k][j]=(mat[j][k]-=g[u][v]);
                            mat[k][k]+=g[u][v];mat[j][j]+=g[u][v];
                        }
                    }
                }
                ans=ans*det(mat,gra[i].size()-1)%MOD;
                for(int j=0;j<len;j++)fa[gra[i][j]]=i;///缩点
            }
        }
        for(int i=0;i<n;i++){
            gra[i].clear();
            ka[i]=fa[i]=Find(i,fa);
        }
    }
    int main()
    {
        scanf("%lld%lld",&n,&m);
        for(int i=0;i<m;i++){
            int u,v,w;
            scanf("%d%d%d",&u,&v,&w);
            u--;v--;
            e[i]=(edge){u,v,w};
        }
        sort(e,e+m,cmp);
        memset(g,0,sizeof(g));
        ans=1;
        for(LL i=0;i<n;i++)ka[i]=fa[i]=i;
        for(LL i=0;i<=m;i++){///边从小到大加入
            if(i&&e[i].w!=e[i-1].w||i==m)///处理完长度为e[i-1].w的所有边
                matrix_tree();///计算生成树
            LL u=Find(e[i].u,fa),v=Find(e[i].v,fa);///连的两个缩点后的点
            if(u!=v){///如果不是一个
                vis[v]=vis[u]=1;
                ka[Find(u,ka)]=Find(v,ka);///两个分量在一个联通块里。
                g[u][v]++,g[v][u]++;///邻接矩阵
            }
        }
        int flag=1;
        for(int i=1;i<n;i++)if(fa[i]!=fa[i-1])flag=0;
        printf("%lld
    ",flag?ans%MOD:0);///注意p可能为1,这样m=0时如果ans不%p就会输出1
        return 0;
    }
    View Code
  • 相关阅读:
    Maven 打包指定子工程项目(springcloud分模块打包)
    linux常见问题: zip/unzip: command not found
    CentOS8安装jdk1.8
    nacos-docker镜像安装nacos并配置数据库
    浏览器的一个请求从发送到返回都经历了什么
    python之scrapy
    常见的爬虫与反爬虫斗争
    Python闭包与延迟绑定
    ip代理
    python编程:统计文件中单词出现次数
  • 原文地址:https://www.cnblogs.com/lalalatianlalu/p/9111615.html
Copyright © 2011-2022 走看看