网络流的一些进阶题

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\n%d\n",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<<"\n";
    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\n",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\n",-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\n", -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\n",-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\n",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\n", i,p[i]);
        }
        add(tt,ss,inf);
        printf("Case %d: ",++cas);
        if(sum==dicnic())
            puts("Yes");
        else puts("No");
    }
}
View Code

猜你喜欢

转载自www.cnblogs.com/MengX/p/11388487.html