• 网络流的一些进阶题


    hdu 6582/bzoj 1266

    最短路建图  两次dijstra求出最短路 然后把最短路的边建网络流

    #include<bits/stdc++.h>
    #define FIN freopen("input.txt","r",stdin)
    #define ll long long
    #define mod 1000000007
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define inf 0x3f3f3f3f
    #define INF 0x3f3f3f3f3f3f3f3f
    const int maxn = 100005;
    using namespace std;
    int cnt,s,t,n,m,k;
    int head[maxn],Next[maxn*20],to[maxn*20];
    int flow[maxn*20],dep[maxn],cur[maxn];
    inline void add(int u,int v,int w){
        Next[cnt]=head[u];
        head[u]=cnt;
        to[cnt]=v;
        flow[cnt++]=w;
    
        Next[cnt]=head[v];
        head[v]=cnt;
        to[cnt]=u;
        flow[cnt++]=0;
    }
    int dfs(int u,int cost){
        if(u==t) return cost;
        for(int &i=cur[u];i!=-1;i=Next[i]){
            if(dep[to[i]]==dep[u]+1&&flow[i]>0){
               int dis=dfs(to[i],min(flow[i],cost));
                if(dis>0){
                    flow[i]-=dis;
                    flow[i^1]+=dis;
                    return dis;
                }
            }
        }
        return 0;
    }
    int bfs(){
        queue<int> q;
        q.push(s);
        memset(dep,0,sizeof(dep));
        dep[s]=1;
        while(!q.empty()){
            int u=q.front();
            q.pop();
            for(int i=head[u];i!=-1;i=Next[i]){
                if(flow[i]>0&&dep[to[i]]==0){
                    dep[to[i]]=dep[u]+1;
                    q.push(to[i]);
                }
            }
        }
        if(dep[t]>0) return 1;
        return 0;
    }
    int dicnic(){
        int ans=0;
        while(bfs()){
            int cost;
            for(int i=0;i<=t+2;i++){
                cur[i]=head[i];
            }
            while(cost=dfs(s,inf))
                ans+=cost;
        }
        return ans;
    }
    int dis[505],vis[505],dis2[505];
    void init(){
        memset(head,-1,sizeof(head));
        memset(dis,inf,sizeof(dis));
        memset(dis2,inf,sizeof(dis2));
        cnt=0;
    }
    struct node{
        int u,v,dis,val;
    }p[124755];
    vector<pair<int,pair<int,int> > > G[505];
    void dijstra(int dis[],int s){
        memset(vis,0,sizeof(vis));
        priority_queue< pair<int,int> , vector<pair<int,int> > ,greater<pair<int,int> > > q;
        q.push({0,s});
        dis[s]=0;
        while(!q.empty()){
            int u=q.top().second;
            q.pop();
            if(vis[u]) continue;
            vis[u]=1;
            int len=G[u].size();
            for(int i=0;i<len;i++){
                int v=G[u][i].first;
                int d=G[u][i].second.first;
                if(dis[v]>dis[u]+d){
                    dis[v]=dis[u]+d;
                    q.push({dis[v],v});
                }
            }
        }
    }
    int main(){
        int n,m;
        init();
        scanf("%d %d",&n,&m);
        for(int i=1;i<=m;i++){
            scanf("%d %d %d %d",&p[i].u,&p[i].v,&p[i].dis,&p[i].val);
            G[p[i].u].push_back({p[i].v,{p[i].dis,p[i].val}});
            G[p[i].v].push_back({p[i].u,{p[i].dis,p[i].val}});
        }
        dijstra(dis,1);
        dijstra(dis2,n);
        for(int i=1;i<=n;i++){
            int len=G[i].size();
            for(int j=0;j<len;j++){
                pair<int,pair<int,int> > x=G[i][j];
                if(dis[i]+dis2[x.first]+x.second.first==dis[n]){
                    add(i,x.first,x.second.second);
                }
            }
    
        }
        s=1;
        t=n;
        printf("%d
    %d
    ",dis[n],dicnic());
        return 0;
    }
    View Code

    bzoj 1305

    二分+最大流 每次check下 是否能满流

    #include<bits/stdc++.h>
    #define FIN freopen("input.txt","r",stdin)
    #define ll long long
    #define mod 1000000007
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define inf 0x3f3f3f3f
    #define INF 0x3f3f3f3f3f3f3f3f
    const int maxn = 100005;
    using namespace std;
    int cnt,s,t,n,m,k;
    int head[maxn],Next[maxn*20],to[maxn*20];
    int flow[maxn*20],dep[maxn],cur[maxn];
    inline void add(int u,int v,int w){
        Next[cnt]=head[u];
        head[u]=cnt;
        to[cnt]=v;
        flow[cnt++]=w;
    
        Next[cnt]=head[v];
        head[v]=cnt;
        to[cnt]=u;
        flow[cnt++]=0;
    }
    int dfs(int u,int cost){
        if(u==t) return cost;
        for(int &i=cur[u];i!=-1;i=Next[i]){
            if(dep[to[i]]==dep[u]+1&&flow[i]>0){
               int dis=dfs(to[i],min(flow[i],cost));
                if(dis>0){
                    flow[i]-=dis;
                    flow[i^1]+=dis;
                    return dis;
                }
            }
        }
        return 0;
    }
    int bfs(){
        queue<int> q;
        q.push(s);
        memset(dep,0,sizeof(dep));
        dep[s]=1;
        while(!q.empty()){
            int u=q.front();
            q.pop();
            for(int i=head[u];i!=-1;i=Next[i]){
                if(flow[i]>0&&dep[to[i]]==0){
                    dep[to[i]]=dep[u]+1;
                    q.push(to[i]);
                }
            }
        }
        if(dep[t]>0) return 1;
        return 0;
    }
    int dicnic(){
        int ans=0;
        while(bfs()){
            int cost;
            for(int i=0;i<=t+2;i++){
                cur[i]=head[i];
            }
            while(cost=dfs(s,inf))
                ans+=cost;
        }
        return ans;
    }
    char mp[55][55];
    void init(){
        memset(head,-1,sizeof(head));
        cnt=0;
    }
    bool check(int f){
        init();
        for(int i=1;i<=n;i++){
            add(s,i,f);
            add(i,i+n,k);
            add(i+2*n,i+3*n,k);
            add(i+3*n,t,f);
        }
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                if(mp[i][j]=='Y'){
                    add(i,j+3*n,1);
                }else {
                    add(i+n,j+2*n,1);
                }
            }
        }
        int res=dicnic();
        if(res==n*f) return true;
        return false;
    }
    int main(){
        scanf("%d %d",&n,&k);
        for(int i=1;i<=n;i++) scanf("%s",mp[i]+1);
        int l=0;
        int r=n;
        int ans=0;
        s=0;
        t=4*n+1;
        while(l<=r){
            int m=(l+r)>>1;
            if(check(m)){
                ans=m;
                l=m+1;
            }else {
                r=m-1;
            }
        }
        cout<<ans<<"
    ";
        return 0;
    }
    View Code

    bzoj 3438

    最大权闭合子图  

    对于每种作物只能种在A或者B 所以 S->i i->T 表示割掉一个

    对于组合同理 

    #include<bits/stdc++.h>
    #define FIN freopen("input.txt","r",stdin)
    #define ll long long
    #define mod 1000000007
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define inf 0x3f3f3f3f
    #define INF 0x3f3f3f3f3f3f3f3f
    const int maxn = 200005;
    using namespace std;
    int cnt,s,t,n,m,k;
    int head[3005],Next[maxn*20],to[maxn*20];
    int flow[maxn*20],dep[3005],cur[3005];
    void add(int u,int v,int w){
        Next[cnt]=head[u];
        head[u]=cnt;
        to[cnt]=v;
        flow[cnt++]=w;
    
        Next[cnt]=head[v];
        head[v]=cnt;
        to[cnt]=u;
        flow[cnt++]=0;
    }
    int dfs(int u,int cost){
        if(u==t) return cost;
        for(int &i=cur[u];i!=-1;i=Next[i]){
            if(dep[to[i]]==dep[u]+1&&flow[i]>0){
               int dis=dfs(to[i],min(flow[i],cost));
                if(dis>0){
                    flow[i]-=dis;
                    flow[i^1]+=dis;
                    return dis;
                }
            }
        }
        return 0;
    }
    int bfs(){
        queue<int> q;
        q.push(s);
        memset(dep,0,sizeof(dep));
        dep[s]=1;
        while(!q.empty()){
            int u=q.front();
            q.pop();
            for(int i=head[u];i!=-1;i=Next[i]){
                if(flow[i]>0&&dep[to[i]]==0){
                    dep[to[i]]=dep[u]+1;
                    if(to[i]==t) return 1;
                    q.push(to[i]);
                }
            }
        }
        if(dep[t]>0) return 1;
        return 0;
    }
    int dicnic(){
        int ans=0;
        while(bfs()){
            int cost;
            for(int i=0;i<=t+2;i++){
                cur[i]=head[i];
            }
            while(cost=dfs(s,inf))
                ans+=cost;
        }
        return ans;
    }
    void init(){
        memset(head,-1,sizeof(head));
        cnt=0;
    }
    int main(){
        init();
        int x;
        scanf("%d",&n);
        int sum=0;
        s=0;
        t=3002;
        for(int i=1;i<=n;i++){
            scanf("%d",&x);
            sum+=x;
            add(s,i,x);
        }
        for(int i=1;i<=n;i++){
            scanf("%d",&x);
            sum+=x;
            add(i,t,x);
        }
        scanf("%d",&m);
        int tot=n+1;
        int a,b;
        while(m--){
            scanf("%d",&k); 
            scanf("%d %d",&a,&b);
            sum+=a+b;
            add(s,++tot,a);
            add(++tot,t,b);
            while(k--){
                scanf("%d",&x);
                add(tot-1,x,inf);
                add(x,tot,inf);
            }
        }
      //  cout<<sum<<" "<<dicnic()<<endl;
        cout<<sum-dicnic()<<endl;
        return 0;
    }
    View Code

    bzoj 3894

    同上题

    #include<bits/stdc++.h>
    #define FIN freopen("input.txt","r",stdin)
    #define ll long long
    #define mod 1000000007
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define inf 0x3f3f3f3f
    #define INF 0x3f3f3f3f3f3f3f3f
    const int maxn = 100005;
    using namespace std;
    int cnt,s,t,n,m,k;
    int head[maxn],Next[maxn*20],to[maxn*20];
    int flow[maxn*20],dep[maxn],cur[maxn];
    int dir[5][2]={0,0,1,0,-1,0,0,1,0,-1};
    inline void add(int u,int v,int w){
        Next[cnt]=head[u];
        head[u]=cnt;
        to[cnt]=v;
        flow[cnt++]=w;
    
        Next[cnt]=head[v];
        head[v]=cnt;
        to[cnt]=u;
        flow[cnt++]=0;
    }
    int dfs(int u,int cost){
        if(u==t) return cost;
        for(int &i=cur[u];i!=-1;i=Next[i]){
            if(dep[to[i]]==dep[u]+1&&flow[i]>0){
               int dis=dfs(to[i],min(flow[i],cost));
                if(dis>0){
                    flow[i]-=dis;
                    flow[i^1]+=dis;
                    return dis;
                }
            }
        }
        return 0;
    }
    int bfs(){
        queue<int> q;
        q.push(s);
        memset(dep,0,sizeof(dep));
        dep[s]=1;
        while(!q.empty()){
            int u=q.front();
            q.pop();
            for(int i=head[u];i!=-1;i=Next[i]){
                if(flow[i]>0&&dep[to[i]]==0){
                    dep[to[i]]=dep[u]+1;
                    q.push(to[i]);
                }
            }
        }
        if(dep[t]>0) return 1;
        return 0;
    }
    int dicnic(){
        int ans=0;
        while(bfs()){
            int cost;
            for(int i=0;i<=t+2;i++){
                cur[i]=head[i];
            }
            while(cost=dfs(s,inf))
                ans+=cost;
        }
        return ans;
    }
    void init(){
        memset(head,-1,sizeof(head));
        cnt=0;
    }
    int id(int i,int j){
        return (i-1)*m+j;
    }
    bool check(int x,int y){
        if(x>n||x<1||y>m||y<1) return true;
        return false;
    }
    int main(){
        int sum=0;
        init();
        scanf("%d %d",&n,&m);
        s=0;
        t=3*n*m+1;
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                scanf("%d",&k);
                sum+=k;
                add(s,id(i,j),k);
            }
        }
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                scanf("%d",&k);
                sum+=k;
                add(id(i,j),t,k);
            }
        }
        int tot=n*m+1;
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                scanf("%d",&k);
                sum+=k;
                add(s,tot,k);
                for(int p=0;p<=4;p++){
                    int fx=i+dir[p][0];
                    int fy=j+dir[p][1];
                    if(check(fx,fy)) continue;
                    add(tot,id(fx,fy),inf);
                }
                tot++;
            }
        }
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                scanf("%d",&k);
                sum+=k;
                add(tot,t,k);
                for(int p=0;p<=4;p++){
                    int fx=i+dir[p][0];
                    int fy=j+dir[p][1];
                    if(check(fx,fy)) continue;
                    add(id(fx,fy),tot,inf);
                }
                tot++;
            }
        }
        printf("%d
    ",sum-dicnic());
        return 0;
    }
    View Code

    hdu 3081

    二分流量 用并查集来判断女生之间的关系 是否已经建图啦

    每次check最大流是否为满流

    #include<bits/stdc++.h>
    #define FIN freopen("input.txt","r",stdin)
    #define ll long long
    #define mod 1000000007
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define inf 0x3f3f3f3f
    #define INF 0x3f3f3f3f3f3f3f3f
    const int maxn = 100005;
    using namespace std;
    int cnt,s,t,n,m,k;
    int head[maxn],Next[maxn*20],to[maxn*20];
    int flow[maxn*20],dep[maxn],cur[maxn];
    int dir[4][2]={1,0,-1,0,0,-1,0,1};
    inline void add(int u,int v,int w){
        Next[cnt]=head[u];
        head[u]=cnt;
        to[cnt]=v;
        flow[cnt++]=w;
    
        Next[cnt]=head[v];
        head[v]=cnt;
        to[cnt]=u;
        flow[cnt++]=0;
    }
    int dfs(int u,int cost){
        if(u==t) return cost;
        for(int &i=cur[u];i!=-1;i=Next[i]){
            if(dep[to[i]]==dep[u]+1&&flow[i]>0){
               int dis=dfs(to[i],min(flow[i],cost));
                if(dis>0){
                    flow[i]-=dis;
                    flow[i^1]+=dis;
                    return dis;
                }
            }
        }
        return 0;
    }
    int bfs(){
        queue<int> q;
        q.push(s);
        memset(dep,0,sizeof(dep));
        dep[s]=1;
        while(!q.empty()){
            int u=q.front();
            q.pop();
            for(int i=head[u];i!=-1;i=Next[i]){
                if(flow[i]>0&&dep[to[i]]==0){
                    dep[to[i]]=dep[u]+1;
                    q.push(to[i]);
                }
            }
        }
        if(dep[t]>0) return 1;
        return 0;
    }
    int dicnic(){
        int ans=0;
        while(bfs()){
            int cost;
            for(int i=0;i<=t+2;i++){
                cur[i]=head[i];
            }
            while(cost=dfs(s,inf))
                ans+=cost;
        }
        return ans;
    }
    int pre[205];
    int vis[205][205],vis2[205][205];
    int _find(int x){
        return x==pre[x]?x:pre[x]=_find(pre[x]);
    }
    void init(){
        memset(head,-1,sizeof(head));
        cnt=0;
    }
    void build(int f){
        init();
        for(int i=1;i<=n;i++){
            for(int j=n+1;j<=2*n;j++){
                vis[i][j]=vis2[i][j];
            }
        }
        s=0;
        t=2*n+1;
        for(int i=1;i<=n;i++){
            for(int j=n+1;j<=2*n;j++){
                if(vis[i][j]) add(i,j,1);
            }
        }
        for(int i=1;i<=n;i++){
            add(s,i,f);
            add(i+n,t,f);
        }
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                if(_find(i)==_find(j)){
                    for(int k=n+1;k<=2*n;k++){
                        if(vis[i][k]&&!vis[j][k]){
                            add(j,k,1);
                            vis[j][k]=1;
                        }
                    }
                }
            }
        }
    
    }
    int main(){
        int T;
        scanf("%d",&T);
        while(T--){ 
            int u,v;
            scanf("%d %d %d",&n,&m,&k);
            memset(vis2,0,sizeof(vis2));
            for(int i=1;i<=n;i++) pre[i]=i;
            for(int i=1;i<=m;i++){
                scanf("%d %d",&u,&v);
                v+=n;
                vis[u][v]=vis2[u][v]=1;
            }
            for(int i=1;i<=k;i++){
                scanf("%d %d",&u,&v);
                int x=_find(u);
                int y=_find(v);
                pre[x]=y;
            }
            int l=0;
            int r=n;
            int ans=0;
            while(l<=r){
                int mid=(l+r)>>1;
                build(mid);
                if(dicnic()==n*mid){
                    ans=mid;
                    l=mid+1;
                }else r=mid-1;   
            }
            cout<<ans<<endl;
        }
        return 0;
    }
    View Code

    hdu 6118

    最小费用最大流/可行流

    #include<bits/stdc++.h>
    #define FIN freopen("input.txt","r",stdin)
    #define ll long long
    #define mod 1000000007
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define inf 0x3f3f3f3f
    #define INF 0x3f3f3f3f3f3f3f3f
    const int maxn = 100005;
    using namespace std;
    int head[maxn],Next[maxn*200],to[maxn*200];
    int flow[maxn*200],dis[maxn],pre[maxn],vis[maxn],id[maxn],ct[maxn];
    int cnt,s,t,n,m;
    inline void add(int u,int v,int w,int cost){
        Next[cnt]=head[u];
        head[u]=cnt;
        to[cnt]=v;
        flow[cnt]=w;
        ct[cnt++]=cost;
    
        Next[cnt]=head[v];
        head[v]=cnt;
        to[cnt]=u;
        flow[cnt]=0;
        ct[cnt++]=-cost;
    }
    bool spfa(){
        memset(vis,0,sizeof(vis));
        memset(dis,inf,sizeof(dis));
        memset(pre,-1,sizeof(pre));
        dis[s]=0;
        queue<int> q;
        q.push(s);
        while(!q.empty()){
            int u=q.front();
            q.pop();
            vis[u]=0;
            for(int i=head[u];i!=-1;i=Next[i]){
                int v=to[i];
                int d=ct[i];
                if(dis[v]>dis[u]+d&&flow[i]>0){
                    dis[v]=dis[u]+d;
                    pre[v]=u;
                    id[v]=i;
                    if(!vis[v]){
                        vis[v]=1;
                        q.push(v);
                    }
                }
            }
        }
       // cout<<dis[t]<=0<<endl;  可行流 不加建图那句 写这个就好了
        return dis[t]<inf;
    }
    int Maxflow(){
        int ans=0;
        while(spfa()){ 
            int Min=inf;
            for(int i=t;i!=s;i=pre[i]){
            //    cout<<i<<" "<<pre[i]<<endl;
                Min=min(flow[id[i]],Min);
            }
            for(int i=t;i!=s;i=pre[i]){
                flow[id[i]]-=Min;
                flow[id[i]^1]+=Min;
            }
            ans+=dis[t]*Min;
           
        }
        return ans;
    }
    void init(){
        memset(head,-1,sizeof(head));
        cnt=0;
        s=0;
        t=n+1;
    }
    int main()
    {
        int a,b,c,d,u,v,w,i;
        while(~scanf("%d%d",&n,&m)){
            int ans=0;
            init();
            for(i=1;i<=n;i++){
                scanf("%d%d%d%d",&a,&b,&c,&d);
                add(s,i,b,a); 
                add(i,t,d,-c); 
                add(i,t,b,-a); //允许不买了! 这样就可以求最大流啦
            }
            for(i=1;i<=m;i++){
                scanf("%d%d%d",&u,&v,&w);
                add(u,v,inf,w); 
                add(v,u,inf,w);  
            }
            printf("%d
    ",-Maxflow());
        }
        return 0;
    }
    View Code

    poj 3680

    同2018焦作网络赛 网络流24题的最长k区间可重

    我们对于区间离散化一下

    其实我们可以把区间看成一条线  其实流量为k 相邻点流量为inf

    每次遇到一个区间都是从左端点流走一条流量为1的流 然后再右端点流回来 

    为啥可以这样 因为起始流量为k 如果再一段区间流出去k条 还没回来那么就没办法再流啦 及 最多k区间可重复

    //#include<bits/stdc++.h>
    #include<cstring>
    #include<cstdio>
    #include<iostream>
    #include<queue>
    #include<map>
    #include<algorithm>
    #define FIN freopen("input.txt","r",stdin)
    #define ll long long
    #define mod 1000000007
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define inf 0x3f3f3f3f
    #define INF 0x3f3f3f3f3f3f3f3f
    const int maxn = 1005;
    using namespace std;
    int cnt,s,t,n,m,k;
    int head[maxn],Next[maxn*200],to[maxn*200];
    int flow[maxn*200],dis[maxn],ct[maxn*200];
    int pre[maxn],vis[maxn],id[maxn];
    void add(int u,int v,int w,int cost){
        Next[cnt]=head[u];
        head[u]=cnt;
        to[cnt]=v;
        flow[cnt]=w;
        ct[cnt++]=cost;
    
        Next[cnt]=head[v];
        head[v]=cnt;
        to[cnt]=u;
        flow[cnt]=0;
        ct[cnt++]=-cost;
    }
    
    inline int read(){
        int x=0,f=1;char ch=getchar();
        while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
        while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    bool spfa(){
        memset(vis,0,sizeof(vis));
        memset(dis,inf,sizeof(dis));
        memset(pre,-1,sizeof(pre));
        dis[s]=0;
        queue<int> q;
        q.push(s);
        while(!q.empty()){
            int u=q.front();
            q.pop();
            vis[u]=0;
            for(int i=head[u];i!=-1;i=Next[i]){
                int v=to[i];
                int d=ct[i];
                if(dis[v]>dis[u]+d&&flow[i]>0){
                    dis[v]=dis[u]+d;
                    pre[v]=u;
                    id[v]=i;
                    if(!vis[v]){
                        vis[v]=1;
                        q.push(v);
                    }
                }
            }
        }
        return dis[t]<inf;
    }
    int Maxflow(){
        int ans=0;
        while(spfa()){ 
            int Min=inf;
            for(int i=t;i!=s;i=pre[i]){
                Min=min(flow[id[i]],Min);
            }
            for(int i=t;i!=s;i=pre[i]){
                flow[id[i]]-=Min;
                flow[id[i]^1]+=Min;
            }
            ans+=dis[t]*Min;
        }
        return ans;
    }
    int q[1005],l[505],r[505],w[505];
    int _;
    void init(){
        memset(head,-1,sizeof(head));
        cnt=0;
        _=0;
    }
    map<int,int> mp;
    int main(){
        int T;
        T=read();
        while(T--){
        n=read();
        k=read();
        init();
        for(int i=1;i<=n;i++){
            l[i]=read();r[i]=read();w[i]=read();
            q[++_]=l[i];
            q[++_]=r[i];
        }
        sort(q+1,q+1+_);
        
        int tot=0;
        for(int i=1;i<=_;i++){
            if(i==1||q[i]!=q[i-1]) mp[q[i]]=++tot;
        }
        for(int i=1;i<tot;i++){
            add(i,i+1,inf,0);
        }
        for(int i=1;i<=n;i++){
            add(mp[l[i]],mp[r[i]],1,-w[i]);
        }
        s=tot+1;
        t=tot+2;
        add(s,1,k,0);
        add(tot,t,k,0);
        printf("%d
    ", -Maxflow());
    }
        return 0;
    }
    View Code

    hdu 6437

    最小费用最大流

    我们先处理能一个接一个看的影片有哪些 同时处理他们的类型

    建立一个次源点 S->S1 容量为k 费用为0 然后通过拆点来限制影片的流量 费用为 -p[i].val 

    最后求出来对最小费用取反就好了

    #include<bits/stdc++.h>
    #define FIN freopen("input.txt","r",stdin)
    #define ll long long
    #define mod 1000000007
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define inf 0x3f3f3f3f
    #define INF 0x3f3f3f3f3f3f3f3f
    const int maxn = 100005;
    using namespace std;
    int head[maxn],Next[maxn*200],to[maxn*200];
    int flow[maxn*200],dis[maxn],pre[maxn],vis[maxn],id[maxn],ct[maxn];
    int cnt,s,t,n,m,k;
    inline void add(int u,int v,int w,int cost){
        Next[cnt]=head[u];
        head[u]=cnt;
        to[cnt]=v;
        flow[cnt]=w;
        ct[cnt++]=cost;
    
        Next[cnt]=head[v];
        head[v]=cnt;
        to[cnt]=u;
        flow[cnt]=0;
        ct[cnt++]=-cost;
    }
    bool spfa(){
        memset(vis,0,sizeof(vis));
        memset(dis,inf,sizeof(dis));
        memset(pre,-1,sizeof(pre));
        dis[s]=0;
        queue<int> q;
        q.push(s);
        while(!q.empty()){
            int u=q.front();
            q.pop();
            vis[u]=0;
            for(int i=head[u];i!=-1;i=Next[i]){
                int v=to[i];
                int d=ct[i];
                if(dis[v]>dis[u]+d&&flow[i]>0){
                    dis[v]=dis[u]+d;    
                    pre[v]=u;
                    id[v]=i;
                    if(!vis[v]){
                        vis[v]=1;
                        q.push(v);
                    }
                }
            }
        }
        return dis[t]<inf;
    }
    int Maxflow(){
        int ans=0;
        while(spfa()){ 
            int Min=inf;
            for(int i=t;i!=s;i=pre[i]){
                Min=min(flow[id[i]],Min);
            }
            for(int i=t;i!=s;i=pre[i]){
                flow[id[i]]-=Min;
                flow[id[i]^1]+=Min;
            }
            ans+=dis[t]*Min;
        }
        return ans;
    }
    void init(){
        memset(head,-1,sizeof(head));
        cnt=0;
    }
    struct node{
        int l,r,op,val;
    }p[205];
    int main(){
        int T,w;
        scanf("%d",&T);
        while(T--){
            init();
            scanf("%d %d %d %d",&n,&m,&k,&w);
            s=0;
            int ss=m+m+1;
            t=m+m+2;
            for(int i=1;i<=m;i++){
                scanf("%d %d %d %d",&p[i].l,&p[i].r,&p[i].val,&p[i].op);
            }
            for(int i=1;i<=m;i++){
                for(int j=1;j<=m;j++){
                    if(i==j) continue;
                    if(p[j].l>=p[i].r){
                        add(i+m,j,1,p[i].op==p[j].op?w:0);
                    }
                }
            }
            add(s,ss,k,0);
            for(int i=1;i<=m;i++){
                add(ss,i,1,0);
                add(i+m,t,1,0);
                add(i,i+m,1,-p[i].val);
            }
            printf("%d
    ",-Maxflow());
        }
        return 0;
    }
    View Code

    hdu 4888

    思路:行与源点连  列与汇点连 行与列连 flow为k(最多可转移k)然后判断是否满流 满流及有解 然后判环就好啦

    代码:无(哈哈哈哈)

    cf 1082G

    最大权闭合子图 (裸)

    #include<bits/stdc++.h>
    #define FIN freopen("input.txt","r",stdin)
    #define ll long long
    #define mod 1000000007
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define inf 0x3f3f3f
    #define INF 0x3f3f3f3f3f3f3f3f
    const int maxn = 200005;
    using namespace std;
    int cnt,s,t,n,m;
    int head[maxn],Next[maxn*20],to[maxn*20],cur[maxn];
    ll flow[maxn*20],dep[maxn];
    inline void add(int u,int v,ll w){
        Next[cnt]=head[u];
        head[u]=cnt;
        to[cnt]=v;
        flow[cnt++]=w;
     
        Next[cnt]=head[v];
        head[v]=cnt;
        to[cnt]=u;
        flow[cnt++]=0;
    }
    ll dfs(int u,ll cost){
        if(u==t) return cost;
        for(int &i=cur[u];i!=-1;i=Next[i]){
            if(dep[to[i]]==dep[u]+1&&flow[i]>0){
               ll dis=dfs(to[i],min(flow[i],cost));
                if(dis>0){
                    flow[i]-=dis;
                    flow[i^1]+=dis;
                    return dis;
                }
            }
        }
        return 0;
    }
    int bfs(){
        queue<int> q;
        q.push(s);
        memset(dep,0,sizeof(dep));
        dep[s]=1;
        while(!q.empty()){
            int u=q.front();
            q.pop();
            for(int i=head[u];i!=-1;i=Next[i]){
                if(flow[i]>0&&dep[to[i]]==0){
                    dep[to[i]]=dep[u]+1;
                    q.push(to[i]);
                }
            }
        }
        if(dep[t]>0) return 1;
        return 0;
    }
    ll dicnic(){
        ll ans=0;
        while(bfs()){
            ll cost;
            for(int i=0;i<=t+2;i++){
                cur[i]=head[i];
            }
            while(cost=dfs(s,INF))
                ans+=cost;
        }
        return ans;
    }
    void init(){
        memset(head,-1,sizeof(head));
        cnt=0;
    }                                                                                      
    int main(){
        scanf("%d %d",&n,&m);
        init();
        s=0;
        t=n+m+1;
        for(int i=1;i<=n;i++){
            int x;
            scanf("%d",&x);
            add(i,t,x);
        }              
        ll ans=0;
        for(int i=1;i<=m;i++){
            int u,v,w;
            scanf("%d %d %d",&u,&v,&w);
            add(i+n,u,INF);
            add(i+n,v,INF);
            add(s,i+n,w);
            ans+=w;
        }        
        printf("%I64d
    ",ans-dicnic());                                                             
        return 0;
    }
    View Code

    GYM 101908G

    https://www.cnblogs.com/MengX/p/11381343.html

    2018沈阳网络赛F

    有汇源上下界网络流板子

    #include<bits/stdc++.h>
    #define FIN freopen("input.txt","r",stdin)
    #define ll long long
    #define mod 1000000007
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define inf 0x3f3f3f3f
    #define INF 0x3f3f3f3f3f3f3f3f
    const int maxn = 100005;
    using namespace std;
    int cnt,s,t,n,m,k;
    int head[maxn],Next[maxn*20],to[maxn*20];
    int flow[maxn*20],dep[maxn],cur[maxn],mp[405][405];
    int dir[8][2]={1,2,1,-2,-1,2,-1,-2,-2,-1,-2,1,2,1,2,-1};
    inline void add(int u,int v,int w){
        Next[cnt]=head[u];
        head[u]=cnt;
        to[cnt]=v;
        flow[cnt++]=w;
    
        Next[cnt]=head[v];
        head[v]=cnt;
        to[cnt]=u;
        flow[cnt++]=0;
    }
    int dfs(int u,int cost){
        if(u==t) return cost;
        for(int &i=cur[u];i!=-1;i=Next[i]){
            if(dep[to[i]]==dep[u]+1&&flow[i]>0){
               int dis=dfs(to[i],min(flow[i],cost));
                if(dis>0){
                    flow[i]-=dis;
                    flow[i^1]+=dis;
                    return dis;
                }
            }
        }
        return 0;
    }
    int bfs(){
        queue<int> q;
        q.push(s);
        memset(dep,0,sizeof(dep));
        dep[s]=1;
        while(!q.empty()){
            int u=q.front();
            q.pop();
            for(int i=head[u];i!=-1;i=Next[i]){
                if(flow[i]>0&&dep[to[i]]==0){
                    dep[to[i]]=dep[u]+1;
                    q.push(to[i]);
                }
            }
        }
        if(dep[t]>0) return 1;
        return 0;
    }
    int dicnic(){
        int ans=0;
        while(bfs()){
            int cost;
            for(int i=0;i<=t+2;i++){
                cur[i]=head[i];
            }
            while(cost=dfs(s,inf))
                ans+=cost;
        }
        return ans;
    }
    int p[200005];
    void init(){
        memset(head,-1,sizeof(head));
        memset(p,0,sizeof(p));
        cnt=0;
    }
    int main(){
        int cas=0;
        while(~scanf("%d %d %d",&n,&m,&k)){
            init();
            int l,r;
            int ss=0;
            int tt=n+m+1;
            s=n+m+2;
            t=n+m+3;
            int sum=0;
            scanf("%d %d",&l,&r);
            for(int i=1;i<=k;i++){
                int u,v;
                scanf("%d %d",&u,&v);
                add(u,v+n,1);
            }
            for(int i=1;i<=n;i++){
                add(ss,i,r-l);
                p[i]+=l;
            }
            for(int i=1;i<=m;i++){
                add(i+n,tt,r-l);
                p[i+n]-=l;
            }
            for(int i=1;i<=n+m;i++){
                if(p[i]<0) add(i,t,-p[i]);
                else add(s,i,p[i]),sum+=p[i];
               // printf("%d ---> %d
    ", i,p[i]);
            }
            add(tt,ss,inf);
            printf("Case %d: ",++cas);
            if(sum==dicnic())
                puts("Yes");
            else puts("No");
        }
    }
    View Code
  • 相关阅读:
    ASP.NET中JSON的序列化和反序列化
    Git 本地项目上传至托管平台(OsChina/GitHub)
    Android Gradle 完整指南(转)
    开发错误记录13:java.lang.UnsatisfiedLinkError: Couldn't load xxx.so: findLibrary returned null
    Android其它新控件 (转)
    一个Activity掌握Design新控件 (转)
    一个Activity掌握Android5.0新控件 (转)
    一个Activity掌握Android4.0新控件 (转)
    开发错误日记 12: Unsupported major.minor version 52.0
    Linux 下各个目录的作用及内容
  • 原文地址:https://www.cnblogs.com/MengX/p/11388487.html
Copyright © 2020-2023  润新知