zoukankan      html  css  js  c++  java
  • 积累一些题

    luogu p2472

    直接最大流,拆点限制经过次数即可

    #include <bits/stdc++.h>
    #define rep(i,l,r) for(int i=l;i<=r;++i)
    #define per(i,l,r) for(int i=r;i>=l;--i)
    using namespace std;
    typedef long long s64;
     
     
    const int M=2e3+5;
     
    int n,m,d;
    char s[25];
    int a[25][25];
    int S,T,dep[M],e_size,head[M];
     
     
    struct edge {
        int v,w,nxt;
    }e[M*10];
     
    void e_add(int u,int v,int w) {
        e[++e_size]=(edge){v,w,head[u]};
        head[u]=e_size;
    }
     
     
    bool Bfs() {
        queue <int> q;
        memset(dep,0,sizeof(dep));
        dep[S]=1;
        q.push(S);
        while (!q.empty()) {
            int r=q.front();
            q.pop();
            for(int i=head[r];i;i=e[i].nxt) {
                int v=e[i].v;
                if(!dep[v]&&e[i].w) {
                    dep[v]=dep[r]+1;
                    q.push(v);
                    if(v==T) return 1;
                }
            }
        }
        return 0;
    }
     
    int Dfs(int x,int cp) {
        if(x==T) return cp;
        int las=cp,q;
        for(int i=head[x];i;i=e[i].nxt) {
            int v=e[i].v;
            if(dep[v]==dep[x]+1&&e[i].w&&las) {
                q=Dfs(v,min(las,e[i].w));
                if(!q) {dep[v]=0;continue;}
                e[i].w-=q,las-=q,e[i^1].w+=q;
                if(!las) break;
            }
        }
        return cp-las;
    }
     
    int main() {
        //freopen("a.in","r",stdin);
     
        scanf("%d%d%d",&n,&m,&d);
        rep(i,1,n) {
            scanf("%s",s+1);
            rep(j,1,m) a[i][j]=s[j]-'0';
        }
     
        S=M-2,T=M-1;
        int ans=0;
     
        e_size=1;
        rep(i,1,n) {
            scanf("%s",s+1);
            rep(j,1,m) if(s[j]=='L') {
                ++ans;
                int x=S,y=i*m-m+j;
                e_add(x,y,1),e_add(y,x,0);
            }
        }
     
        rep(i,1,n) rep(j,1,m) if(a[i][j]) {
            int x=i*m-m+j,y=x+n*m;
            e_add(x,y,a[i][j]),e_add(y,x,0);
        }
     
        rep(i,1,n) rep(j,1,m) if(a[i][j]) {
            bool vis=0;
            int u=i*m-m+j+n*m;
            rep(x,i-d,i+d) rep(y,j-d,j+d) {
                if((x-i)*(x-i)+(y-j)*(y-j)>d*d) continue;
                if(x<1||y<1||x>n||y>m) {
                    if(!vis) vis=1,e_add(u,T,1e5),e_add(T,u,0);
                }
                else if(a[x][y]) {
                    int v=x*m-m+y;
                    //cout<<u<<" "<<v<<endl;
                    e_add(u,v,1e5),e_add(v,u,0);
                }
            }
        }
        
        while (Bfs()) ans-=Dfs(S,1e5);
     
        cout<<ans<<endl;
    }
    bzoj 1066

    luogu p3305

    显然二分+最大流 

    #include <bits/stdc++.h>
    #define rep(i,l,r) for(int i=l;i<=r;++i)
    #define per(i,l,r) for(int i=r;i>=l;--i)
    using namespace std;
    typedef long long s64;
     
    const int M=1e3+5;
    const double eps=1e-10;
     
    int n,m;
    double p,a[M*10];
    int e_size,head[M],dep[M];
     
    struct edge {
        int v;
        double w;
        int nxt;
    }e[M*10];
     
    void e_add(int u,int v,double w) {
        e[++e_size]=(edge) {v,w,head[u]};
        head[u]=e_size;
        a[e_size]=w;
    }
     
     
    bool Bfs() {
        queue <int> q;
        memset(dep,0,sizeof(dep));
        dep[1]=1;
        q.push(1);
        while (!q.empty()) {
            int r=q.front();
            q.pop();
            for(int i=head[r];i;i=e[i].nxt) {
                int v=e[i].v;
                if(!dep[v]&&e[i].w>eps) {
                    dep[v]=dep[r]+1;
                    q.push(v);
                    if(v==n) return 1;
                }
            }
        }
        return 0;
    }
     
    double Dfs(int x,double cp) {
        if(x==n) return cp;
        double las=cp,q;
        for(int i=head[x];i;i=e[i].nxt) {
            int v=e[i].v;
            if(dep[v]==dep[x]+1&&e[i].w>eps&&las>eps) {
                q=Dfs(v,min(las,e[i].w));
                if(q<eps) {dep[v]=0;continue;}
                e[i].w-=q,las-=q,e[i^1].w+=q;
            }
        }
        return cp-las;
    }
     
     
    double calc(double Min) {
        rep(i,2,e_size) e[i].w=min(Min,a[i]);
     
        double ans=0;
        while (Bfs()) ans+=Dfs(1,1e9);
        return ans;
    }
     
    int main() {
        //freopen("a.in","r",stdin);
        scanf("%d%d%lf",&n,&m,&p);
        e_size=1;
        rep(i,1,m) {
            int x,y;
            double c;
            scanf("%d%d%lf",&x,&y,&c);
            e_add(x,y,c),e_add(y,x,0);
        }
     
        double ans=0;
        while (Bfs()) ans+=Dfs(1,1e9);
        printf("%.0f
    ",ans);
     
        double l=0,r=5e4,mid;
        while (l+eps<r) {
            mid=(l+r)/2;
            if(calc(mid)+eps>ans) r=mid;
            else l=mid;
        }
        printf("%.4f
    ",r*p);
    }
    bzoj 3130

    luogu p5038

    偶数想出来了,显然可以二分,然后直接黑白染色就行了

    奇数可以直接解出答案check。。。

    #include <bits/stdc++.h>
    #define rep(i,l,r) for(int i=l;i<=r;++i)
    #define per(i,l,r) for(int i=r;i>=l;--i)
    using namespace std;
    typedef long long s64;
    
    const int M=3e3+5;
    int n,m;
    int S,T,a[55][55];
    int e_size,head[M],dep[M];
    int x_[4]={0,0,-1,1},y_[4]={1,-1,0,0};
    
    struct edge {
        int u,v;
        s64 w;
        int nxt;
    }e[M*10];
    
    void e_add(int u,int v,s64 w) {
        e[++e_size]=(edge){u,v,w,head[u]};
        head[u]=e_size;
    }
    
    
    bool Bfs() {
        queue <int> q;
        memset(dep,0,sizeof(dep));
        dep[S]=1;
        q.push(S);
    
        while (!q.empty()) {
            int r=q.front();
            q.pop();
            for(int i=head[r];i;i=e[i].nxt) {
                int v=e[i].v;
                if(!dep[v]&&e[i].w) {
                    dep[v]=dep[r]+1;
                    q.push(v);
                    if(v==T) return 1;
                }
            }
        }
        return 0;
    }
    
    s64 Dfs(int x,s64 cp) {
        if(x==T) return cp;
        s64 las=cp,q;
        for(int i=head[x];i;i=e[i].nxt) {
            int v=e[i].v;
            if(dep[v]==dep[x]+1&&e[i].w&&las) {
                q=Dfs(v,min(e[i].w,las));
                if(!q) {dep[v]=0;continue;}
                e[i].w-=q,e[i^1].w+=q,las-=q;
            }
        }
        return cp-las;
    }
    
    bool check(s64 val) {
        e_size=1;
        memset(head,0,sizeof(head));
        s64 tot=0;
        rep(i,1,n) rep(j,1,m) {
            int x=i*m-m+j;
            tot+=val-a[i][j];
            if(i+j&1) e_add(S,x,val-a[i][j]),e_add(x,S,0);
            else      e_add(x,T,val-a[i][j]),e_add(T,x,0);
        }
    
        rep(i,1,n) rep(j,1,m) if(i+j&1) rep(k,0,3) {
            int x=i+x_[k],y=j+y_[k];
            int u=i*m-m+j,v=x*m-m+y;
            if(!(x<1||y<1||x>n||y>m)) e_add(u,v,1e18),e_add(v,u,0);
        }
    
        s64 sum=0;
        while (Bfs()) sum+=Dfs(S,1e18);
        return sum==tot/2;
    }
    
    int main() {
        //freopen("a.in","r",stdin);
        int test_;
        scanf("%d",&test_);
        while (test_--) {
            S=M-2,T=S+1;
    
            int mx=0;
            s64 cnt[2]={0};
            s64 sum[2]={0};
            scanf("%d%d",&n,&m);
            rep(i,1,n) rep(j,1,m) {
                scanf("%d",a[i]+j);
                mx=max(mx,a[i][j]);
                ++cnt[i+j&1],sum[i+j&1]+=a[i][j];
            }
    
            if(cnt[0]!=cnt[1]) {
                s64 ans=(sum[0]-sum[1])/(cnt[0]-cnt[1]);
                if(ans<mx||!check(ans)) puts("-1");
                else printf("%lld
    ",ans*n*m-sum[0]-sum[1]>>1);
            }
            else {
                if(sum[0]!=sum[1]) puts("-1");
                else {
                    s64 l=mx,r=1e16,mid,ans=-1;
                    while (l<=r) {
                        mid=l+r>>1;
                        if(check(mid)) ans=mid,r=mid-1;
                        else l=mid+1;
                    }
                    if(ans==-1) puts("-1");
                    else printf("%lld
    ",ans*n*m-sum[0]-sum[1]>>1);
                }
            }
        }
    }
    bzoj 2756

    luogu p4542

    一个裸的上下界可行流

    注意最短路用floyd保证经过的点都小于等于k

    #include <queue>
    #include <cstdio>
    #include <vector>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #define rep(i,l,r) for(int i=l;i<=r;++i)
    #define per(i,l,r) for(int i=l;i>=r;--i)
    using namespace std;
    typedef long long s64;
    
    const int M=3e2+10;
    
    int n,m,K;
    int S,T,a[M][M];
    int dis[M],inq_[M],pre[M];
    int e_size,head[M];
    
    struct edge{
        int u,v,w,c,nxt;
    }e[M*M*10];
    
    void e_add(int u,int v,int w,int c) {
        e[++e_size]=(edge){u,v,w,c,head[u]};
        head[u]=e_size;
    }
    
    
    void insert(int u,int v,int w,int c) {
        e_add(u,v,w,c),e_add(v,u,0,-c);
    }
    
    void spfa() {
        queue <int> q;
        memset(inq_,0,sizeof(inq_));
        memset(dis,0x7f,sizeof(dis));
        
        dis[S]=0;
        q.push(S);
        while (!q.empty()) {
            int r=q.front();
            q.pop();
            inq_[r]=0;
            for(int i=head[r];i;i=e[i].nxt) {
                int v=e[i].v;
                if(e[i].w&&dis[v]>dis[r]+e[i].c) {
                    pre[v]=i;
                    dis[v]=dis[r]+e[i].c;
                    if(!inq_[v]) q.push(v),inq_[v]=1;
                }
            }
        }
    }
    
    int feiyong() {
        int ans=0;
        while (spfa(),dis[T]<2e9) {
            int t=2e9;
            for(int i=pre[T];i;i=pre[e[i].u]) t=min(t,e[i].w);
            //cout<<t<<endl;
            ans+=t*dis[T];
            for(int i=pre[T];i;i=pre[e[i].u]) e[i].w-=t,e[i^1].w+=t;
        }
        return ans;
    }
    
    int main() {
        //freopen("a.txt","r",stdin);
        scanf("%d%d%d",&n,&m,&K);
        
        ++n;
        memset(a,0x3f,sizeof(a));
        rep(i,1,n) a[i][i]=0;
        rep(i,1,m) {
            int x,y,z;
            scanf("%d%d%d",&x,&y,&z);
            ++x,++y;
            if(z<a[x][y]) a[x][y]=a[y][x]=z;
        }
        
        
        
        
        e_size=1;
        rep(u,1,n) {
            rep(i,1,n) rep(j,1,n) a[i][j]=min(a[i][j],a[i][u]+a[u][j]);
            if(u>1) insert(2*n+3,u,1e9,a[1][u]);
            rep(i,2,u-1) insert(i+n,u,1e9,a[i][u]);
        }
        insert(n+1,1,1e9,0);
        insert(1,2*n+3,K,0);
        rep(i,2,n) {
            insert(i,i+n,1e9,0);
            insert(i+n,n+1,1e9,0);
        }
        
        
        S=2*n+1,T=S+1;
        rep(i,2,n) insert(S,i+n,1,0),insert(i,T,1,0);
        
        printf("%d
    ",feiyong());
    }
    luogu 4542

    luogu p2805

    tarjan去掉不可能吃的plants之后裸的最大权闭合子图

    #include <bits/stdc++.h>
    #define rep(i,l,r) for(int i=l;i<=r;++i)
    #define per(i,l,r) for(int i=l;i>=r;--i)
    using namespace std;
    typedef long long s64;
    
    
    const int M=1e5+5;
    
    int n,m;
    int a[55][55];
    bool not_[M];
    int be[M],dfn[M],low[M],time_,size[M];
    int S,T,e_size,head[M],dep[M];
    
    stack <int> sta;
    
    vector <int> to[M];
    
    struct edge {
        int v,w,nxt;
    }e[M*10];
    
    void e_add(int u,int v,int w) {
        e[++e_size]=(edge){v,w,head[u]};
        head[u]=e_size;
    }
    
    void insert(int u,int v,int w) {
        e_add(u,v,w),e_add(v,u,0);
    }
    
    
    void tarjan(int x) {
        dfn[x]=low[x]=++time_;
        sta.push(x);
        
        for(auto v:to[x]) {
            if(!dfn[v]) {
                tarjan(v);
                low[x]=min(low[x],low[v]);
            }
            else if(!be[v]) low[x]=min(low[x],dfn[v]);
        }
        
        if(low[x]==dfn[x]) {
            be[0]++;
            while(1) {
                ++size[be[0]];
                int t=sta.top();
                sta.pop();
                be[t]=be[0];
                if(x==t) break;
            }
        }
    }
    
    
    
    bool Bfs() {
        queue <int> q;
        memset(dep,0,sizeof(dep));
        q.push(S);
        dep[S]=1;
        while (!q.empty()) {
            int r=q.front();
            q.pop();
            for(int i=head[r];i;i=e[i].nxt) {
                int v=e[i].v;
                if(!dep[v]&&e[i].w) {
                    dep[v]=dep[r]+1;
                    q.push(v);
                    if(v==T) return 1;
                }
            }
        }
        return 0;
    }
    
    int Dfs(int x,int cp) {
        if(x==T) return cp;
        int las=cp,q;
        for(int i=head[x];i;i=e[i].nxt) {
            int v=e[i].v;
            if(dep[v]==dep[x]+1&&las&&e[i].w) {
                q=Dfs(v,min(e[i].w,las));
                if(!q) {dep[v]=0;continue;}
                las-=q,e[i].w-=q,e[i^1].w+=q;
            }
        }
        return cp-las;
    }
    
    int main() {
        //freopen("a.txt","r",stdin);
        
        scanf("%d%d",&n,&m);
        rep(i,1,n) rep(j,1,m) {
            scanf("%d",a[i]+j);
            int cnt,x,y;
            scanf("%d",&cnt);
            rep(k,1,cnt) {
                scanf("%d%d",&x,&y);
                ++x,++y;
                to[i*m-m+j].push_back(x*m-m+y);
            }
            if(j>1) to[i*m-m+j].push_back(i*m-m+j-1);
        }
        
        rep(i,1,n*m) if(!dfn[i]) tarjan(i);
        rep(i,1,n*m) if(size[be[i]]>1) not_[i]=1;
        rep(i,1,n*m) per(j,m-1,1) if(not_[i*m-m+j+1]) not_[i*m-m+j]=1;
        
        
        e_size=1;
        int ans=0;
        S=n*m+1,T=S+1;
        rep(i,1,n) rep(j,1,m) {
            int x=i*m-m+j;
            if(not_[x]) continue;
            for(auto v:to[x]) if(!not_[v]) insert(v,x,1e9);
            ans+=max(0,a[i][j]);
            if(a[i][j]>0) insert(S,x,a[i][j]);
            else          insert(x,T,-a[i][j]);
        }
        
        while (Bfs()) ans-=Dfs(S,1e9);
        cout<<ans<<endl;
        
        return 0;
    }
    luogu p2805

    luogu p3749

    裸的最大权闭合子图

    #include <queue>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define rep(i,l,r) for(int i=l;i<=r;++i)
    #define per(i,l,r) for(int i=l;i>=r;--i)
    using namespace std;
    typedef long long s64;
    
    
    const int M=1e2+5;
    const int N=1e4+5;
    const int inf=0x7fffffff;
    
    int n,m;
    int S,T;
    int a[M],b[M][M],id[M][M];
    int e_size,dep[N],head[N];
    
    
    struct edge{
        int v,w,nxt;
    }e[N*10];
    
    void e_add(int u,int v,int w) {
        e[++e_size]=(edge){v,w,head[u]};
        head[u]=e_size;
    }
    
    void insert(int u,int v,int w) {
        e_add(u,v,w),e_add(v,u,0);
    }
    
    bool Bfs() {
        queue <int> q;
        memset(dep,0,sizeof(dep));
    
        dep[S]=1;
        q.push(S);
        while (!q.empty()) {
            int r=q.front();
            q.pop();
            for(int i=head[r];i;i=e[i].nxt) {
                int v=e[i].v;
                if(!dep[v]&&e[i].w) {
                    dep[v]=dep[r]+1;
                    q.push(v);
                    if(v==T) return 1;
                }
            }
        }
        return 0;
    }
    
    int Dfs(int x,int cp) {
        if(x==T) return cp;
        int las=cp,q;
        for(int i=head[x];i;i=e[i].nxt) {
            int v=e[i].v;
            if(dep[v]==dep[x]+1&&e[i].w&&las) {
                q=Dfs(v,min(e[i].w,las));
                if(!q) {dep[v]=0;continue;}
                las-=q,e[i].w-=q,e[i^1].w+=q;
            }
        }
        return cp-las;
    }
    
    int main() {
        //freopen("a.txt","r",stdin);
        //printf("%d
    ",inf);
        scanf("%d%d",&n,&m);
        rep(i,1,n) scanf("%d",a+i);
        rep(i,1,n) rep(j,i,n) scanf("%d",b[i]+j),id[i][j]=++id[0][0];
        rep(i,1,n) b[i][i]-=a[i];
    
        int ans=0;
        e_size=1;
        S=id[n][n]+1001,T=S+1;
        rep(i,1,n) rep(j,i,n) {
            ans+=max(0,b[i][j]);
            if(i==j) {
                insert(id[i][j],a[i]+id[n][n],inf);
                b[i][j]>0?insert(S,id[i][j],b[i][j]):insert(id[i][j],T,-b[i][j]);
            }
            else {
                insert(id[i][j],id[i][j-1],inf);
                insert(id[i][j],id[i+1][j],inf);
                b[i][j]>0?insert(S,id[i][j],b[i][j]):insert(id[i][j],T,-b[i][j]);
            }
        }
    
        sort(a+1,a+n+1);
        a[0]=a[1]-1;
        rep(i,1,n) if(a[i]!=a[i-1]) insert(id[n][n]+a[i],T,m*a[i]*a[i]);
    
    
        while(Bfs()) ans-=Dfs(S,inf);
        printf("%d
    ",ans);
    }
    bzoj 4873

    luogu p4126

    需要仔细想一下条件

    可能在:u,v不在一个scc内(即所有条件下都满流)

    必须在:S和u在一个scc内,v和T在一个scc内(若不删这条边就可以增广)

    #include <queue>
    #include <stack>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define rep(i,l,r) for(int i=l;i<=r;++i)
    #define per(i,l,r) for(int i=l;i>=r;--i)
    using namespace std;
    typedef long long s64;
    
    
    const int M=4e3+5;
    const int N=6e4+5;
    const int inf=0x7fffffff;
    
    int n,m,S,T;
    int dep[M],e_size,head[M];
    int be[M],low[M],dfn[M],time_;
    stack <int> sta;
    
    struct edge{
        int u,v,w,nxt;
    }e[N*10];
    
    void e_add(int u,int v,int w) {
        e[++e_size]=(edge){u,v,w,head[u]};
        head[u]=e_size;
    }
    
    bool Bfs() {
        queue <int> q;
        memset(dep,0,sizeof(dep));
    
        dep[S]=1;
        q.push(S);
        while (!q.empty()) {
            int r=q.front();
            q.pop();
            for(int i=head[r];i;i=e[i].nxt) {
                int v=e[i].v;
                if(!dep[v]&&e[i].w) {
                    dep[v]=dep[r]+1;
                    q.push(v);
                    if(v==T) return 1;
                }
            }
        }
        return 0;
    }
    
    int Dfs(int x,int cp) {
        if(x==T) return cp;
        int las=cp,q;
        for(int i=head[x];i;i=e[i].nxt) {
            int v=e[i].v;
            if(dep[v]==dep[x]+1&&e[i].w&&las) {
                q=Dfs(v,min(e[i].w,las));
                if(!q) {dep[v]=0;continue;}
                las-=q,e[i].w-=q,e[i^1].w+=q;
            }
        }
        return cp-las;
    }
    
    
    void tarjan(int x) {
        low[x]=dfn[x]=++time_;
        sta.push(x);
    
        for(int i=head[x];i;i=e[i].nxt) {
            int v=e[i].v;
            if(!e[i].w) continue;
            if(!dfn[v]) {
                tarjan(v);
                low[x]=min(low[x],low[v]);
            }
            else if(!be[v]) low[x]=min(low[x],dfn[v]);
        }
    
        
        if(low[x]==dfn[x]) {
            ++be[0];
            while(1) {
                int tmp=sta.top();
                sta.pop();
                be[tmp]=be[0];
                if(x==tmp) break;
            }
        }
    }
    
    int main() {
        //freopen("a.txt","r",stdin);
        scanf("%d%d%d%d",&n,&m,&S,&T);
        e_size=1;
        rep(i,1,m) {
            int u,v,w;
            scanf("%d%d%d",&u,&v,&w);
            e_add(u,v,w),e_add(v,u,0);
        }
    
        while (Bfs()) Dfs(S,inf);
    
        rep(i,1,n) if(!dfn[i]) tarjan(i);//脑残吗
    
        for(int i=2;i<=e_size;i+=2) {
            if(e[i].w) puts("0 0");
            else {
                be[e[i].u]==be[e[i].v]?printf("0 "):printf("1 ");
                be[e[i].u]==be[S]&&be[e[i].v]==be[T]?puts("1"):puts("0");
            }
        }
    }
    bzoj 1797

    bzoj 3281

    边转化为点用支配树求出必经边

    因为必经点所以$dis[nxt]-dis[pre]$就是最短路径

    得到数列单调指针覆盖即可

    注意脑子不清醒写的代码一定要重写

    #include <set>
    #include <stack>
    #include <ctime>
    #include <queue>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #define fir first
    #define sec second
    #define rep(i,l,r) for(int i=(l);i<=(r);++i)
    #define per(i,l,r) for(int i=(l);i>=(r);--i)
    using namespace std;
    typedef long long s64;
     
     
    const int M=5e5+5;
    int n,m,S,T,len;
    int head[M],e_size,dis[M];
    int st[M],id[M],sdom[M],idom[M];
    int be[M],f[M],fa[M],sta[M],g[M];
     
     
    bool vis[M];
     
    vector <int> to[M],pre[M],buc[M];
     
    struct edge{
        int u,v,w,nxt;
    }e[M*5];
     
    void e_add(int u,int v,int w) {
        e[++e_size]=(edge){u,v,w,head[u]};
        head[u]=e_size;
    }
     
     
    void dijkstra() {
        rep(i,1,n) dis[i]=2147483647;
        dis[S]=0;
        set <pair<int,int> > q;
        q.insert(make_pair(0,S));
        int cnt=0;
        while (!q.empty()) {
            ++cnt;
            pair<int,int> r=*q.begin();
            q.erase(q.begin());
            if(dis[r.sec]!=r.fir) continue;
            for(int i=head[r.sec];i;i=e[i].nxt) {
                int v=e[i].v;
                if(dis[v]>dis[r.sec]+e[i].w) {
                    dis[v]=dis[r.sec]+e[i].w;
                    q.insert(make_pair(dis[v],v));
                }
            }
        }
    }
     
    void dfs(int x) {
        id[x]=++id[0];
        st[id[0]]=x;
     
        be[x]=x;
        f[x]=x;
        sdom[x]=id[x];//
     
        for(int v,i=to[x].size()-1;i>=0;--i) {
            v=to[x][i];
            if(!id[v]) fa[v]=x,dfs(v);
        }
    }
     
    int find(int x) {
        if(x==be[x]) return f[x];
        int now=find(be[x]);
        be[x]=be[be[x]];
        if(sdom[now]<sdom[f[x]]) f[x]=now;
        return f[x];
    }
     
    void make_dominator_tree() {
        rep(i,1,m) {
            int u=e[i].u,v=e[i].v;
             
            to[u].push_back(n+i);
            to[n+i].push_back(v);
     
            pre[n+i].push_back(u);
            pre[v].push_back(n+i);
        }
     
        dfs(S);
     
        per(i,id[0],2) {
            int p=st[i];
            for(int i=pre[p].size()-1;i>=0;--i) {
                int v=pre[p][i];
                if(id[v]) sdom[p]=min(sdom[p],sdom[find(v)]);
            }
            be[p]=fa[p];
     
     
            buc[st[sdom[p]]].push_back(p);
     
            for(int i=buc[fa[p]].size()-1;i>=0;--i) {
                int v=buc[fa[p]][i];
                int u=find(v);
     
                if(sdom[u]==sdom[v]) vis[v]=1,idom[v]=sdom[v];
                else idom[v]=u;
            }
        }
        rep(i,2,id[0]) if(!vis[st[i]]) idom[st[i]]=idom[idom[st[i]]];//vis[st[i]]啊
    }
     
     
    void get_ans() {
        int cnt=0;
        int pre=-1,now=st[idom[T]];
        while (now&&now<=n) now=st[idom[now]];
     
        while (now) {
            if(pre!=-1) {
                sta[++cnt]=dis[e[pre-n].u]-dis[e[now-n].v];
            }
            sta[++cnt]=e[now-n].w;
     
     
            pre=now;
            now=st[idom[now]];
            while (now&&now<=n) now=st[idom[now]];
        }
     
        int tot=0;
        rep(i,1,cnt+1>>1) tot+=sta[2*i-1];
        int ans=tot;
     
        for(int l=cnt,r=cnt,num=0,sum[2]={0};l>=1;--l) {
            num+=sta[l]*(l&1);
            sum[0]+=sta[l],sum[1]+=sta[l]*(l&1);
            while (sum[0]>2*len) sum[0]-=sta[r],sum[1]-=sta[r]*(r&1),--r;
            ans=min(ans,tot-sum[1]-(r+1<=cnt&&r+1&1)*(2*len-sum[0]));
        }
     
        for(int l=cnt,r=cnt,num=0,sum[2]={0};l>=1;--l) {
            num+=sta[l]*(l&1);
            sum[0]+=sta[l],sum[1]+=sta[l]*(l&1);
            while (sum[0]>len) sum[0]-=sta[r],sum[1]-=sta[r]*(r&1),--r;
            g[l]=num-sum[1]-(r+1<=cnt&&r+1&1)*(len-sum[0]);
        }
        per(i,cnt-1,1) g[i]=min(g[i],g[i+1]+sta[i]*(i&1));
        for(int l=1,r=1,num=0,sum[2]={0};l<=cnt;++l) {
            num+=sta[l]*(l&1);
            sum[0]+=sta[l],sum[1]+=sta[l]*(l&1);
            while (sum[0]>len) sum[0]-=sta[r],sum[1]-=sta[r]*(r&1),++r;
            ans=min(ans,g[l+1]+num-sum[1]-(r-1>=1&&r-1&1)*(len-sum[0]));
        }
     
        printf("%d
    ",ans);
    }
     
    int main() {
        //freopen("a.txt","r",stdin);
        int test_;
        scanf("%d",&test_);
        while (test_--) {
     
            scanf("%d%d%d%d%d",&n,&m,&S,&T,&len);
            ++S,++T;
            rep(i,1,m) {
                int x,y,z;
                scanf("%d%d%d",&x,&y,&z);
                ++x,++y;
                e_add(x,y,z);
            }
     
     
            dijkstra();
     
            if(dis[T]>1000000000) puts("-1");
            else{
                make_dominator_tree();
                get_ans();
            }
     
            e_size=0;
            rep(i,0,n+m) f[i]=g[i]=be[i]=fa[i]=id[i]=st[i]=vis[i]=sta[i]=idom[i]=sdom[i]=head[i]=0;
            rep(i,1,n+m) to[i].clear(),pre[i].clear(),buc[i].clear();
        }
    }
    bzoj 3281

    bzoj 3495

    2-sat

    加一个前缀和优化即可

    #include <set>
    #include <stack>
    #include <ctime>
    #include <queue>
    #include <cstdio>
    #include <vector>
    #include <cstring>
    #include <iostream>
    #define fir first
    #define sec second
    #define rep(i,l,r) for(int i=(l);i<=(r);++i)
    #define per(i,l,r) for(int i=(l);i>=(r);--i)
    using namespace std;
    typedef long long s64;
     
    const int M=4e6+5;
    int n,m,K;
    int a[M],be[M];
    int low[M],dfn[M],time_;
    stack <int> sta;
     
    int e_size,head[M];
    struct edge{
        int v,nxt;
    }e[M*5];
     
    void e_add(int u,int v) {
        e[++e_size]=(edge){v,head[u]};
        head[u]=e_size;
    }
     
    void tarjan(int x) {
        //cout<<"-_-"<<x<<endl;
        low[x]=dfn[x]=++time_;
        sta.push(x);
     
        for(int i=head[x];i;i=e[i].nxt) {
            int v=e[i].v;
            //cout<<x<<" "<<v<<endl;
            if(!dfn[v]) {
                tarjan(v);
                low[x]=min(low[x],low[v]);
            }
            else if(!be[v]) low[x]=min(low[x],dfn[v]);
        }
     
        if(low[x]==dfn[x]) {
            ++be[0];
            while (1) {
                int tmp=sta.top();
                sta.pop();
                be[tmp]=be[0];
                if(x==tmp) break;
            }
        }
    }
     
     
    int main() {
        //freopen("a.txt","r",stdin);
        scanf("%d%d%d",&n,&m,&K);
        rep(i,1,m) {
            int x,y;
            scanf("%d%d",&x,&y);
            e_add(2*x-1,2*y);
            e_add(2*y-1,2*x);
        }
     
        int cnt=2*n;
        rep(i,1,K) {
            //cout<<"-_-"<<endl;
            int num;
            scanf("%d",&num);
            rep(j,1,num) scanf("%d",a+j);
     
            int pre=2*a[1]-1;
            rep(j,2,num) {
                e_add(2*a[j],pre);
                ++cnt;
                e_add(cnt,2*a[j]-1);
                e_add(cnt,pre);
                pre=cnt;
            }
     
            pre=2*a[num]-1;
            per(j,num-1,1) {
                e_add(2*a[j],pre);
                ++cnt;
                e_add(cnt,2*a[j]-1);
                e_add(cnt,pre);
                pre=cnt;
            }
        }
     
        rep(i,1,2*n) if(!dfn[i]) tarjan(i);
     
        rep(i,1,n) if(be[2*i]==be[2*i-1]) return puts("NIE"),0;
        puts("TAK");
    }
    bzoj 3495

    bzoj 2730

    点双连通分量

    分析后发现给只包含一个割点的强连通分量放一个出口即可

    特判没有割点的情况

    #include <set>
    #include <stack>
    #include <ctime>
    #include <queue>
    #include <cstdio>
    #include <vector>
    #include <cstring>
    #include <iostream>
    #define fir first
    #define sec second
    #define rep(i,l,r) for(int i=(l);i<=(r);++i)
    #define per(i,l,r) for(int i=(l);i>=(r);--i)
    using namespace std;
    typedef long long s64;
    typedef unsigned long long u64;
     
    const int M=1e4+5;
     
    int n,m;
    int e_size,head[M];
    int low[M],dfn[M],time_,be;
    bool is_cut[M];
     
    vector <int> cc[M];
     
    stack <int> sta;
     
    struct edge{
        int v,nxt;
    }e[M*5];
     
    void e_add(int u,int v) {
        e[++e_size]=(edge){v,head[u]};
        head[u]=e_size;
    }
     
     
    void tarjan(int x,int las) { 
        low[x]=dfn[x]=++time_;
     
        sta.push(x);
     
        int c=0;
        for(int i=head[x];i;i=e[i].nxt) {
            int v=e[i].v;
            if(v==las) continue;
            if(!dfn[v]) {
                int pre=sta.top();
                tarjan(v,x);
                low[x]=min(low[x],low[v]);
                if(low[v]>=dfn[x]) {
                    ++c;
                    is_cut[x]=1;
     
                    ++be;
                    while (1) {
                        int tmp=sta.top();
                        if(tmp==pre) break;
                        sta.pop();
                        cc[be].push_back(tmp);
                    }
                    cc[be].push_back(x);
                }
            }
            else low[x]=min(low[x],dfn[v]);
        }
     
        if(x==las&&c==1) is_cut[x]=0;
    }
     
     
    int main() {
        //freopen("a.txt","r",stdin);
        int test_=0;
        while (scanf("%d",&m)==1) {
            if(!m) break;
            n=0;
            rep(i,1,m) {
                int x,y;
                scanf("%d%d",&x,&y);
                n=max(n,max(x,y));
                e_add(x,y),e_add(y,x);
            }
     
            rep(i,1,n) if(!dfn[i]) tarjan(i,i);
     
            if(be==1) {
                printf("Case %d: 2 %lld
    ",++test_,1ll*n*(n-1)/2);
            }
            else {
                u64 ans[2]={0};
                ans[1]=1;
                rep(i,1,be) {
                    int t=0;
                    for(int j=cc[i].size()-1;j>=0;--j) t+=is_cut[cc[i][j]];
                    if(t==1) ++ans[0],ans[1]*=cc[i].size()-1;
                }
                printf("Case %d: %llu %llu
    ",++test_,ans[0],ans[1]);
            }
     
            time_=e_size=0;
            rep(i,1,n) low[i]=dfn[i]=head[i]=is_cut[i]=0;
            rep(i,1,be) cc[i].clear();
            be=0;
        }
    }
    bzoj 2730

    bzoj 5219

    竞赛图计数简单题

    #include <set>
    #include <stack>
    #include <ctime>
    #include <queue>
    #include <cstdio>
    #include <vector>
    #include <cstring>
    #include <iostream>
    #define fir first
    #define sec second
    #define rep(i,l,r) for(int i=(l);i<=(r);++i)
    #define per(i,l,r) for(int i=(l);i>=(r);--i)
    using namespace std;
    typedef long long s64;
    typedef unsigned long long u64;
     
     
    const int M=2e3+5;
     
    int n,mod;
    int C[M][M];
    int f[M],g[M],bin[M];
     
    int qpow(int x,int k) {
        int t=1;
        for(;k;k>>=1,x=1ll*x*x%mod) if(k&1) t=1ll*t*x%mod;
        return t;
    }
     
    void inc(int &x,int y) {x+=y,x-=x>=mod?mod:0;}
     
    int main() {
        //freopen("a.txt","r",stdin);
        scanf("%d%d",&n,&mod);
        rep(i,0,n) C[i][0]=1;
        rep(i,1,n) rep(j,1,i) inc(C[i][j]=C[i-1][j],C[i-1][j-1]);
     
        rep(i,0,n) bin[i]=qpow(2,i*(i-1)>>1);
     
        rep(i,1,n) {
            g[i]=bin[i];
            rep(j,1,i-1) inc(g[i],mod-1ll*C[i][j]*g[j]%mod*bin[i-j]%mod);
        }
     
        //rep(i,1,n) cout<<g[i]<<" "; cout<<endl;
        rep(i,1,n) {
            int ans=0;
            rep(j,0,i-1) inc(ans,1ll*C[i-1][j]*g[j+1]%mod*bin[i-j-1]%mod);
            ans=1ll*ans*C[n-1][i-1]%mod*bin[n-i]%mod;
            printf("%d
    ",ans);
        }
        puts("");
    }
    bzoj 5219

    bzoj 3693

    Hall定理

    求$|S|-|T|$最小值显然枚举的$|S|$中的组的区间并是连续的

    转化为枚举区间,求出区间包含的组的$a_{i}$的和即可

    左端点单调用线段树维护右端点的区间加减求min即可

    $O(n*logn)$

    #include <set>
    #include <stack>
    #include <ctime>
    #include <queue>
    #include <cstdio>
    #include <vector>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #define fir first
    #define sec second
    #define rep(i,l,r) for(int i=(l);i<=(r);++i)
    #define per(i,l,r) for(int i=(l);i>=(r);--i)
    using namespace std;
    typedef long long s64;
    typedef unsigned long long u64;
     
    const int M=5e5+5;
    int n,m;
    int st[M],sta[M];
    int Min[M*4],data[M*4];
      
    struct node{
        int x,id;
      
        bool operator <(const node &a) const {
            return x<a.x;
        }
    }p[M];
      
      
    struct point {
        int l,r,x;
      
        bool operator <(const point &a) const {
            return l<a.l;
        }
    }a[M];
      
    void push_down(int g) {
        data[g<<1]+=data[g];
        data[g<<1|1]+=data[g];
      
        Min[g<<1]+=data[g];
        Min[g<<1|1]+=data[g];
          
        data[g]=0;
    }
      
      
    void T_add(int g,int l,int r,int lx,int rx,int x) {
        if(lx<=l&&rx>=r) return Min[g]+=x,data[g]+=x,void();
      
        if(data[g]) push_down(g);
      
        int mid=l+r>>1;
        if(lx<=mid) T_add(g<<1,l,mid,lx,rx,x);
        if(rx>mid)  T_add(g<<1|1,mid+1,r,lx,rx,x);
      
        Min[g]=min(Min[g<<1],Min[g<<1|1]);
    }
      
    int query(int g,int l,int r,int lx,int rx) {
        if(lx<=l&&rx>=r) return Min[g];
      
        if(data[g]) push_down(g);
      
        int ans=2e9;
        int mid=l+r>>1;
        if(lx<=mid) ans=min(ans,query(g<<1,l,mid,lx,rx));
        if(rx>mid)  ans=min(ans,query(g<<1|1,mid+1,r,lx,rx));
        return ans;
    }
      
    signed main() {
        //freopen("a.txt","r",stdin);
        //freopen("a.out","w",stdout);
        int test_;
        scanf("%d",&test_);
        while (test_--) {
            scanf("%d%d",&n,&m);
      
            s64 sum=0;
            rep(i,1,n) {
                scanf("%d%d%d",&a[i].l,&a[i].r,&a[i].x);
                if(a[i].l>a[i].r) a[i].r+=m;
                sum+=a[i].x;
            }
            if(sum>m) {
                puts("No");
                continue;
            }
     
            int cnt=n;
            rep(i,1,n) if(a[i].r<m) a[++cnt]=(point){a[i].l+m,a[i].r+m,a[i].x};
            n=cnt;
      
            rep(i,1,n) p[2*i-1]=(node){a[i].l,2*i-1},p[2*i]=(node){a[i].r,2*i};
            sort(p+1,p+2*n+1);
            p[0].x=p[1].x-1;
            rep(i,1,2*n) {
                if(p[i].x!=p[i-1].x) ++st[0];
                st[st[0]]=p[i].x;
                sta[p[i].id]=st[0];
            }
            rep(i,1,n) a[i].l=sta[2*i-1],a[i].r=sta[2*i];
      
            sort(a+1,a+n+1);
            rep(i,1,st[0]) T_add(1,1,st[0],i,i,st[i]-st[1]+1);
            rep(i,1,n) T_add(1,1,st[0],a[i].r,st[0],-a[i].x);
            //rep(i,1,st[0]) cout<<query(1,1,st[0],i,i)<<" "; cout<<endl;while (1);
      
            int ans=0;
            int head_=1,tail_=1;
            rep(i,1,st[0]) {
                while (tail_+1<=st[0]&&st[tail_+1]-st[i]<m) ++tail_;
                ans=query(1,1,st[0],i,tail_);
                if(ans<0) break;
      
                while (a[head_].l==i) T_add(1,1,st[0],a[head_].r,st[0],a[head_].x),++head_;
                T_add(1,1,st[0],i,st[0],st[i]-st[i+1]);
            }
            ans<0?puts("No"):puts("Yes");
     
            st[0]=0;
            rep(i,0,16*n) Min[i]=data[i]=0;
        }
    }
    bzoj 3693

    bzoj 3894

    最小割

    将st看作文理

    新建(s,x',same_art)并用same_art限制5个点即可

    same_sci同理对称新建点即可

    #include <queue>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #define rep(i,l,r) for(int i=l;i<=r;++i)
    #define per(i,l,r) for(int i=r;i>=l;--i)
    using namespace std;
    typedef long long s64;
     
    const int N=105;
    const int M=4e4+5;
    const int inf=2e9;
      
    int n,m;
    int art[N][N],sci[N][N];
    int same_art[N][N],same_sci[N][N];
    int S,T,dep[M],e_size,head[M];
    int x_[4]={0,0,1,-1},y_[4]={1,-1,0,0};
      
    struct edge {
        int v,w,nxt;
    }e[M*10];
      
    void e_add(int u,int v,int w) {
        e[++e_size]=(edge){v,w,head[u]};
        head[u]=e_size;
    }
     
    void insert(int u,int v,int w) {
        e_add(u,v,w),e_add(v,u,0);
    }
      
      
    bool Bfs() {
        queue <int> q;
        memset(dep,0,sizeof(dep));
        dep[S]=1;
        q.push(S);
        while (!q.empty()) {
            int r=q.front();
            q.pop();
            for(int i=head[r];i;i=e[i].nxt) {
                int v=e[i].v;
                if(!dep[v]&&e[i].w) {
                    dep[v]=dep[r]+1;
                    q.push(v);
                    if(v==T) return 1;
                }
            }
        }
        return 0;
    }
      
    int Dfs(int x,int cp) {
        if(x==T) return cp;
        int las=cp,q;
        for(int i=head[x];i;i=e[i].nxt) {
            int v=e[i].v;
            if(dep[v]==dep[x]+1&&e[i].w&&las) {
                q=Dfs(v,min(las,e[i].w));
                if(!q) {dep[v]=0;continue;}
                e[i].w-=q,las-=q,e[i^1].w+=q;
                if(!las) break;
            }
        }
        return cp-las;
    }
      
    int main() {
        //freopen("a.txt","r",stdin);
        S=M-2,T=M-1;
        e_size=1;
     
        scanf("%d%d",&n,&m);
        rep(i,1,n) rep(j,1,m) scanf("%d",art[i]+j);
        rep(i,1,n) rep(j,1,m) scanf("%d",sci[i]+j);
        rep(i,1,n) rep(j,1,m) scanf("%d",same_art[i]+j);
        rep(i,1,n) rep(j,1,m) scanf("%d",same_sci[i]+j);
     
     
        int ans=0;
        rep(i,1,n) rep(j,1,m) {
            ans+=art[i][j]+sci[i][j];
            ans+=same_art[i][j]+same_sci[i][j];
            int x=(i-1)*m+j;
            insert(S,x,art[i][j]);
            insert(x,T,sci[i][j]);
            insert(x,x+n*m,inf);
            insert(x+n*m,T,same_sci[i][j]);
            insert(S,x+2*n*m,same_art[i][j]);
            insert(x+2*n*m,x,inf);
     
            rep(k,0,3) {
                int ii=i+x_[k],jj=j+y_[k];
                if(ii<1||ii>n||jj<1||jj>m) continue;
                int xx=(ii-1)*m+jj;
     
                insert(x+2*n*m,xx,inf);
                insert(xx,x+n*m,inf);
            }
        }
     
        while (Bfs()) ans-=Dfs(S,inf);
        cout<<ans<<endl;
    }
    bzoj 3894

    bzoj 3436

    差分约束裸题

  • 相关阅读:
    #define IOFFSETOF(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
    互联网地址处理例程
    Android系统工程模式启动过程详解
    知识填充
    git 本地回退
    理解JS中的Promise对象
    MySQL server version for the right syntax to use near 'identified
    尾递归要注意的点
    事件捕获和事件冒泡的理解
    v 2ra-y_build_a_sever_in_vltru
  • 原文地址:https://www.cnblogs.com/asd123www/p/11038826.html
Copyright © 2011-2022 走看看