ybtoj Au 网络流模型及应用

前言中的前言

  1. 由于本人过菜,有些题解会咕掉,请原谅这个蒟蒻

  2. 由于本人过菜,不知道什么时候就 AFO 了,想给这个机房留下点什么……

  3. 如果想看高效进阶的题解,建议出门左拐,去云落那里看看,保证是全网最全最好的,但不要对云落的博客好奇,更不要看云落的一言 和 云落的合集:黑夜刀己,白日爱人

正片开始!

好耶!!!(泪目)

题面

题目传送门

前言

本章虽然叫网络流模型及应用,但其实就是最小割

最小割 T1,板子题

正文

割贡献,第 x 个任务和第 y 个任务如果在不同的机器上完成,则增加 v 的花费。

这条就在 x y 之间连双向边即可

代码

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N=1e6+6;
const int inf=0x3f3f3f3f3f3f3f3f;
int n,m;
int s,t,head[N],cnt=1;
struct node{int to,nxt,w;}e[N];
void add(int u,int v,int w){
	e[++cnt].to=v;
	e[cnt].nxt=head[u];
	e[cnt].w=w;
	head[u]=cnt;
}
int ans=0;
int deep[N],now[N];
bool bfs(){
	for(int i=s;i<=t;i++)deep[i]=inf;
	deep[s]=0;
	now[s]=head[s];
	queue<int> q;
	q.push(s);
	while(!q.empty()){
		int u=q.front();q.pop();
		for(int i=head[u];~i;i=e[i].nxt){
			int v=e[i].to;
			if(e[i].w&&deep[v]==inf){
				deep[v]=deep[u]+1;
				now[v]=head[v];
				q.push(v);
				if(v==t)return 1;
			}
		}
	}
	return 0;
}
int dfs(int u,int sum){
	if(u==t)return sum;
	int k,flow=0;
	for(int i=now[u];~i&&sum;i=e[i].nxt){
		now[u]=i;
		int v=e[i].to;
		if(e[i].w&&(deep[v]==deep[u]+1)){
			k=dfs(v,min(sum,e[i].w));
			if(k==0)deep[v]=inf;
			e[i].w-=k;
			e[i^1].w+=k;
			flow+=k;
			sum-=k;
		}
	}
	return flow;
}
signed main(){
	cin>>n>>m;
	t=n+1;
	memset(head,-1,sizeof(head));
	for(int i=1;i<=n;i++){
		int a,b;
		cin>>a>>b;
		add(s,i,a),add(i,s,0);
		add(i,t,b),add(t,i,0);
	}
	for(int i=1;i<=m;i++){
		int x,y,w;
		cin>>x>>y>>w;
		add(x,y,w),add(y,x,0),add(y,x,w),add(x,y,0);
	}
	while(bfs())ans+=dfs(s,inf);
	cout<<ans;
	return 0;
}

后记

好困好困

题面

题目传送门

前言

最小割 T2,应用题

正文

对于同时选的点,我们新建一个点 x 用于绑定,s -> x ,容量为 w

代码

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N=1e6+6;
const int inf=0x3f3f3f3f3f3f3f3f;
int n,m;
int S,T,s,t,head[N],cnt1=1;
struct node{int to,nxt,w;}e[N];

int id(int x, int y)
{
    return (x - 1) * m + y;
}
void add(int u,int v,int w){
	e[++cnt1].to=v;
	e[cnt1].nxt=head[u];
	e[cnt1].w=w;
	head[u]=cnt1;
	e[++cnt1].to=u;
	e[cnt1].nxt=head[v];
	e[cnt1].w=0;
	head[v]=cnt1;
}
int ans=0;
int deep[N],now[N];
bool bfs(){
	for(int i=s;i<=t;i++)deep[i]=inf;
	deep[s]=0;
	now[s]=head[s];
	queue<int> q;
	q.push(s);
	while(!q.empty()){
		int u=q.front();q.pop();
		for(int i=head[u];~i;i=e[i].nxt){
			int v=e[i].to;
			if(e[i].w&&deep[v]==inf){
				deep[v]=deep[u]+1;
				now[v]=head[v];
				q.push(v);
				if(v==t)return 1;
			}
		}
	}
	return 0;
}
int dfs(int u,int sum){
	if(u==t)return sum;
	int k,flow=0;
	for(int i=now[u];~i&&sum;i=e[i].nxt){
		now[u]=i;
		int v=e[i].to;
		if(e[i].w&&(deep[v]==deep[u]+1)){
			k=dfs(v,min(sum,e[i].w));
			if(k==0)deep[v]=inf;
			e[i].w-=k;
			e[i^1].w+=k;
			flow+=k;
			sum-=k;
		}
	}
	return flow;
}
int tot;
signed main(){
	cin>>n>>m;
	memset(head,-1,sizeof(head));
    int tmp = n * m;
    s = 0;
    t = n * m + (n - 1) * m * 2 + n * (m - 1) * 2 + 1;
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            int x;
            cin >> x;
            add(s, (i - 1) * m + j, x);
            tot += x;
        }
    }
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            int x;
            cin >> x;
            add((i - 1) * m + j, t, x);
            tot += x;
        }
    }
    for (int i = 1; i < n; i++) {
        for (int j = 1; j <= m; j++) {
            int x;
            cin >> x;
            tot += x;
            add(s, ++tmp, x);
            add(tmp, (i - 1) * m + j, inf);
            add(tmp, i * m + j, inf);
        }
    }
    for (int i = 1; i < n; i++) {
        for (int j = 1; j <= m; j++) {
            int x;
            cin >> x;
            tot += x;
            add(++tmp, t, x);
            add((i - 1) * m + j, tmp, inf);
            add(i * m + j, tmp, inf);
        }
    }
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j < m; j++) {
            int x;
            cin >> x;
            tot += x;
            add(s, ++tmp, x);
            add(tmp, (i - 1) * m + j, inf);
            add(tmp, (i - 1) * m + j + 1, inf);
        }
    }
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j < m; j++) {
            int x;
            cin >> x;
            tot += x;
            add(++tmp, t, x);
            add((i - 1) * m + j, tmp, inf);
            add((i - 1) * m + j + 1, tmp, inf);
        }
    }
	while(bfs())ans+=dfs(s,inf);
	cout<<tot-ans;
	return 0;
}

后记

网络流水紫真的好多啊

题面

题目传送门

前言

最小割 T3,水题

正文

奖金和代价是不能共存的,所以我们要割~

代码

#include <bits/stdc++.h>
using namespace std;
const int inf=1e9+9;
const int N=1e6+6;
int m,n,s,t,tot,head[N],cnt=1;
struct node{int to,nxt,w;}e[N];
void add(int u,int v,int w){
	e[++cnt].to=v;
	e[cnt].nxt=head[u];
	head[u]=cnt;
	e[cnt].w=w;
}
int ans,deep[N],now[N];
bool bfs(){
	for(int i=0;i<=N-5;i++)deep[i]=inf;
	//cout<<deep[s]<<endl;
	deep[s]=0;
	now[s]=head[s];
	queue<int> q;
	q.push(s);
	//cout<<q.empty();
	while(!q.empty()){
		int u=q.front();q.pop();
		//cout<<u<<endl;
		for(int i=head[u];i;i=e[i].nxt){
			int v=e[i].to;
			//cout<<v<<" ";
			if(deep[v]==inf&&e[i].w){
				q.push(v);
				now[v]=head[v];
				deep[v]=deep[u]+1;
				if(v==t)return 1;
			}
		}
	}
	return 0;
}
int dfs(int u,int sum){
	if(u==t)return sum;
	int k,flow=0;
	for(int i=now[u];i&&sum;i=e[i].nxt){
		int v=e[i].to;
		now[u]=i;
		if((deep[v]==deep[u]+1)&&e[i].w){
			k=dfs(v,min(sum,e[i].w));
			if(!k)deep[v]=inf;
			e[i].w-=k;
			e[i^1].w+=k;
			sum-=k;
			flow+=k;
		}
	}
	return flow;
}
int main(){
	cin>>m>>n;
	t=m+n+1;
	for(int i=1;i<=m;i++){
		int x;
		cin>>x;
		tot+=x;
		add(s,i,x),add(i,s,0);
		while(getchar()==' '){
			cin>>x;
			add(i,x+m,inf);
			add(x+m,i,0);
		}
	}
	for(int i=1;i<=n;i++){
		int x;
		cin>>x;
		add(i+m,t,x);
		add(t,i+m,0);
	}
	while(bfs())ans+=dfs(s,inf);
	
	for(int i=1;i<=m;i++)if(deep[i]!=inf)cout<<i<<" ";
	cout<<endl;
	for(int i=1;i<=n;i++)if(deep[i+m]!=inf)cout<<i<<" ";
	cout<<endl<<tot-ans;
	return 0;
}

后记

好摆啊

题面

题目传送门

前言

最小割 T4,典题

正文

割完之后分别从 s t dfs 一下,因为是要唯一的,所以不存在一个点既不属于 s 也不属于 t(即可以属于 s 也可以属于 t

代码

#include <bits/stdc++.h>
using namespace std;
const int N=1e6+6;
const int inf=1e9+9;
int n,m,s,t,tot,cnt,head[N];
bool vis[N];
struct node{int to,nxt,w;}e[N];
void add(int u,int v,int w){
	e[++cnt].to=v;
	e[cnt].nxt=head[u];
	head[u]=cnt;
	e[cnt].w=w;
}
int now[N],deep[N];
bool bfs(){
	for(int i=0;i<N-5;i++)deep[i]=inf;
	now[s]=head[s];
	deep[s]=0;
	queue<int>q;
	q.push(s);
	while(!q.empty()){
		int u=q.front();
		q.pop();
		for(int i=head[u];i;i=e[i].nxt){
			int v=e[i].to;
			if(e[i].w&&deep[v]==inf){
				deep[v]=deep[u]+1;
				now[v]=head[v];
				q.push(v);
				if(v==t)return 1;
			}
		}
	}
	return 0;
}
int dfs(int u,int sum){
	if(u==t)return sum;
	int k,flow=0;
	for(int i=head[u];i&&sum;i=e[i].nxt){
		int v=e[i].to;
		if(e[i].w&&(deep[v]==deep[u]+1)){
			k=dfs(v,min(e[i].w,sum));
			if(!k)deep[v]=inf;
			e[i].w-=k;
			e[i^1].w+=k;
			flow+=k;
			sum-=k;
		}
	}
	return flow;
}
void dfs1(int u){
	for(int i=head[u];i;i=e[i].nxt){
		int v=e[i].to;
		if(!vis[v]&&e[i].w){
			tot++;
			vis[v]=1;
			dfs1(v);
		}
	}
}
void dfs2(int u){
	for(int i=head[u];i;i=e[i].nxt){
		int v=e[i].to;
		if(!vis[v]&&e[i^1].w){
			tot++;
			vis[v]=1;
			dfs2(v);
		}
	}
}
int ans;
int main(){
	cin>>n>>m>>s>>t;
	while(n!=0&&m!=0){
		tot=2,cnt=1,ans=0;
		memset(head,0,sizeof(head));
		memset(vis,0,sizeof(vis));
		for(int i=1;i<=m;i++){
			int x,y,z;
			cin>>x>>y>>z;
			add(x,y,z),add(y,x,z);
		}
		while(bfs())ans+=dfs(s,inf);
		vis[s]=vis[t]=1;
		dfs1(s),dfs2(t);
		if(tot==n)cout<<"UNIQUE"<<endl;
		else cout<<"AMBIGUOUS"<<endl;
		cin>>n>>m>>s>>t;
	}
	return 0;
}

后记

昨天梦见教练不让我去浙江……,醒了还没反应过来……

题面

题目传送门

前言

最小割 T5,云落秒了题

正文

其实最后呢,题意就可以转化为判 edx>0

e 为边数,d 为点数,x 为二分出来的值

所以我们就从 s 向每条边连一条容量为 1 的边,每条边向他的点连 inf 边,每个点向 t 连容量为 x 的边

代码

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N=100005;
const int inf=1e18;
int n,m,u[N],v[N],head[N<<4],cnt=1;
double eps=1e-8;
struct node{int to,nxt;double w;}e[N<<4];
void add(int u,int v,double w){
	e[++cnt].to=v;
	e[cnt].w=w;
	e[cnt].nxt=head[u];
	head[u]=cnt;
}
int s,t,now[N],deep[N];
bool bfs(){
	for(int i=1;i<=t;i++)deep[i]=inf;
	deep[s]=0;
	now[s]=head[s];
	queue<int> q;
	q.push(s);
	while(!q.empty()){
		int u=q.front();
		q.pop();
		for(int i=head[u];i;i=e[i].nxt){
			int v=e[i].to;
			if(e[i].w&&deep[v]==inf){
				q.push(v);
				deep[v]=deep[u]+1;
				now[v]=head[v];
				if(v==t)return 1;
			}
		}
	}
	return 0;
}
double dfs(int u,double sum){
	if(u==t)return sum;
	double k,flow=0;
	for(int i=head[u];i&&sum;i=e[i].nxt){
		int v=e[i].to;
		if(e[i].w&&(deep[v]==deep[u]+1)){
			k=dfs(v,min(e[i].w,sum));
			if(!k)deep[v]=inf;
			e[i].w-=k;
			e[i^1].w+=k;
			flow+=k;
			sum-=k;
		}
	}
	return flow;
}
double op;
bool check(double x){
	cnt=1;
	s=m+n+1,t=s+1;
    for(int i=1;i<=t;i++)head[i]=0;
	for(int i=1;i<=m;i++){
		add(s,i+n,1);
		add(i+n,s,0);
		add(i+n,u[i],inf);
		add(u[i],i+n,0);
		add(i+n,v[i],inf);
		add(v[i],i+n,0);
	}
	for(int i=1;i<=n;i++){
		add(i,t,x);
		add(t,i,0);
	}
    op=0;
	while(bfs()){
		op+=dfs(s,inf);
	}
   // cout<<op<<endl;
	return m-op>0;
}
int tot;
bool vis[N];
void dfs1(int x){
	vis[x]=1;
	for(int i=head[x];i;i=e[i].nxt){
		int v=e[i].to;
		double w=e[i].w;
		if(!vis[v]&&w)dfs1(v);
	}
}
vector<int> o;
signed main(){
	while(cin>>n>>m){
        memset(vis,0,sizeof(vis));
        if(m==0){cout<<1<<endl<<1<<endl;continue;}
		for(int i=1;i<=m;i++){
			cin>>u[i]>>v[i];
		}
		double l=0,r=2e9,ans=-1;
		while(l+eps<r){
			double mid=(l+r)/2;
			//cout<<mid<<endl;
			if(check(mid))ans=mid,l=mid;
			else r=mid;
		}
		check(ans);
		dfs1(s);
        tot=0;
        o.clear();
		for(int i=1;i<=n;i++){
			if(vis[i]){
				o.push_back(i);
				tot++;
			}
		}
		cout<<tot<<endl;
		for(int i:o)cout<<i<<endl;
        cout<<endl;
	}
	return 0;
}

后记

多测为啥过不了啊啊啊

题面

题目传送门

前言

最小割 T6,水题

正文

同 T2

代码

#include <bits/stdc++.h>
using namespace std;
const int N=1e6;
const int inf=1e9;
int dx[6]={0,0,0,-1,1};
int dy[6]={0,-1,1,0,0};
int n,m,o,s,t,head[N],cnt=1;
struct node{int to,nxt,w;}e[N];
int id(int x,int y){return (x-1)*m+y;}
void add(int u,int v,int w){
    e[++cnt].to=v;
    e[cnt].nxt=head[u];
    e[cnt].w=w;
    head[u]=cnt;
}
int res,ans;
int deep[N],now[N];
bool bfs(){
    for(int i=1;i<=o;i++)deep[i]=inf;
    now[s]=head[s];
    deep[s]=0;
    queue<int> q;
    q.push(s);
    while(!q.empty()){
        int u=q.front();
        q.pop();
        for(int i=head[u];i;i=e[i].nxt){
            int v=e[i].to;
            if(e[i].w&&deep[v]==inf){
                deep[v]=deep[u]+1;
                now[v]=head[v];
                q.push(v);
                if(v==t)return 1;
            }
        }
    }
    return 0;
}
int dfs(int u,int sum){
    if(u==t)return sum;
    int k,flow=0;
    for(int i=now[u];i&&sum;i=e[i].nxt){
        int v=e[i].to;
        now[u]=i;
        if(e[i].w&&(deep[v]==deep[u]+1)){
            k=dfs(v,min(e[i].w,sum));
            if(!k)deep[v]=inf;
            e[i].w-=k;
            e[i^1].w+=k;
            sum-=k;
            flow+=k;
        }
    }
    return flow;
}
int main(){
    cin>>n>>m;
    t=id(n,m)+1,s=0;
    o=t;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            int a;
            cin>>a;
            res+=a;
            add(s,id(i,j),a);
            add(id(i,j),s,0);
           // cout<<s<<" "<<id(i,j)<<endl;
        }
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            int a;
            cin>>a;
            res+=a;
            add(id(i,j),t,a);
            add(t,id(i,j),0);
          //  cout<<id(i,j)<<" "<<t<<endl;
        }
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            o++;
            int a;
            cin>>a;
            res+=a;
            add(s,o,a);
            add(o,s,0);
      //      cout<<s<<" "<<o<<endl;
            for(int k=0;k<=4;k++){
                int u=i+dx[k],v=j+dy[k];
                if(u>=1&&u<=n&&v>=1&&v<=m){
                    add(o,id(u,v),inf);
                    add(id(u,v),o,0);
        //            cout<<o<<" "<<id(u,v)<<endl;
                }
            }
        }
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            o++;
            int a;
            cin>>a;
            res+=a;
            add(o,t,a);
            add(t,o,0);
         //   cout<<o<<" "<<t<<endl;
            for(int k=0;k<=4;k++){
                int u=i+dx[k],v=j+dy[k];
                if(u>=1&&u<=n&&v>=1&&v<=m){
                    add(id(u,v),o,inf);
                    add(o,id(u,v),0);
        //            cout<<o<<" "<<id(u,v)<<endl;
                }
            }
        }
    }
    while(bfs())ans+=dfs(s,inf);
    cout<<res-ans<<endl;
    return 0;
}

后记

切力

题面

题目传送门

前言

最小割 T7,毒瘤题

正文

横竖不能交叉,考虑割

那么我们拆点,把一个点拆成横点和竖点,中间连 inf

对于每个炮塔,到最大值的路径上两两连边,容量为最大值减边的起点的权值,所以,如果切了一条边就相当于打了这条边的起点,到最大值是因为打最大值往后的点更劣

代码

#include<bits/stdc++.h>
#define ll long long

#define rep(i,s,e) for(int i=(s);i<=(e);++i)

using namespace std;
inline int read(){
    int x=0,f=1;
    char ch=getchar();
    while(ch>'9'||ch<'0'){if(ch=='-') f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
    return x*f;
}
const int N=6005;
const int dx[]={0,-1,1,0,0};
const int dy[]={0,0,0,-1,1};
int n,m,a[55][55],s,t,mp[55][55];
int head[N],rad[N],cnt=1;
struct qwq{
    int u,v,w,nxt;
}e[N*N<<1];
struct qaq{
    int x,y,op,tx,ty,mx;
};
vector<qaq> g;
inline void add(int u,int v,int w){
    // cout<<u<<' '<<v<<' '<<w<<endl;
    e[++cnt]={u,v,w,head[u]},head[u]=cnt;
    e[++cnt]={v,u,0,head[v]},head[v]=cnt;
}
namespace dinic{
    int dep[N];
    inline bool bfs(){
        queue<int> q;
        rep(i,1,t) dep[i]=0;
        dep[s]=1,q.push(s);
        while(!q.empty()){
            int x=q.front();q.pop();
            rad[x]=head[x];
            for(int i=head[x];i;i=e[i].nxt){
                int v=e[i].v,w=e[i].w;
                if(!dep[v]&&w) dep[v]=dep[x]+1,q.push(v);
            }
        }
        return dep[t]!=0;
    }
    int dfs(int x,int flow){
        if(x==t) return flow;
        int out=0;
        for(int &i=rad[x];i;i=e[i].nxt){
            int v=e[i].v,&w=e[i].w;
            if(dep[v]==dep[x]+1&&w){
                int res=dfs(v,min(w,flow));
                out+=res,flow-=res,w-=res,e[i^1].w+=res;
            }
            if(!flow) break;
        }
        if(flow) dep[x]=-1;
        return out;
    }
    inline int solve(){
        int ans=0,tmp;
        while(bfs()) while(tmp=dfs(s,1e9)) ans+=tmp;
        return ans;
    }
}
inline bool pd(int x,int y){return x>=1&&x<=n&&y>=1&&y<=m;}
signed main(){
    n=read(),m=read();
    int id=0;
    rep(i,1,n) rep(j,1,m) a[i][j]=read(),mp[i][j]=++id;
    rep(i,1,n) rep(j,1,m) if(a[i][j]<0){
        int op=-a[i][j],x=i,y=j,mx=0,tx=i,ty=j;
        while(1){
            x+=dx[op],y+=dy[op];
            if(!pd(x,y)) break;
            if(mx<a[x][y]) mx=a[x][y],tx=x,ty=y;
        }
        g.push_back({i,j,op,tx,ty,mx}),a[i][j]=0;
    }
    rep(i,1,id) add(i,id+i,1e9);
    int tot=0;s=id<<1|1,t=s+1;
    for(qaq now:g){
        int i=now.x,j=now.y,op=now.op,mx=now.mx,pre;
        tot+=mx;
        if(op<=2){
            add(mp[i][j]+id,t,1e9);
            int x=now.tx,y=now.ty;
            pre=mp[x][y]+id;
            if(x==i&&y==j) continue;
            while(1){
                x-=dx[op],y-=dy[op];
                add(pre,mp[x][y]+id,mx-a[x][y]),pre=mp[x][y]+id;
                if(x==i&&y==j) break;
            }
        }
        else{
            add(s,mp[i][j],1e9),pre=mp[i][j];
            int x=i,y=j,pw=mx;
            if(x==now.tx&&y==now.ty) continue;
            while(1){
                x+=dx[op],y+=dy[op];
                add(pre,mp[x][y],pw);
                pw=mx-a[x][y],pre=mp[x][y];
                if(x==now.tx&&y==now.ty) break;
            }
        }
    }
    printf("%d\n",tot-dinic::solve());
}

后记

好困好困

题面

题目传送门

前言

最小割 T8,综合题

正文

首先,式子是很好推的

D=(ABC)AT

D=i=1n(j=1najbj,ici)ai

D=i=1nj=1naiajbi,ji=1naici

对于每一个B矩阵中的元素 bi,j

如果不要他(即 aiaj 中有至少一个为0),就损失 bi,j,

否则就必须损失 cicj(因为此时 aiaj 皆为1)

代码

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int M=5e6+6;
const int N=1005;
const int inf=9e18;
int n,b[N][N],c[N],s,t,head[M],cnt=1,res,ans;
struct node{int to,nxt,w;}e[M];
void add(int u,int v,int w){
	e[++cnt].to=v;
	e[cnt].nxt=head[u];
	head[u]=cnt;
	e[cnt].w=w;
}
int id(int x,int y){return (x-1)*n+y;}
int now[M],deep[M];
bool bfs(){
	now[s]=head[s];
	for(int i=0;i<=t;i++)deep[i]=inf;
	deep[s]=0;
	queue<int> q;
	q.push(s);
	while(!q.empty()){
		int u=q.front();
		q.pop();
		for(int i=head[u];i;i=e[i].nxt){
			int v=e[i].to;
			if(e[i].w&&deep[v]==inf){
				deep[v]=deep[u]+1;
				now[v]=head[v];
				q.push(v);
				if(v==t)return 1;
			}
		}
	}
	return 0;
}
int dfs(int u,int sum){
	if(u==t)return sum;
	int k,flow=0;
	for(int i=now[u];i&&sum;i=e[i].nxt){
		now[u]=i;
		int v=e[i].to;
		if(e[i].w&&(deep[v]==deep[u]+1)){
			k=dfs(v,min(sum,e[i].w));
			if(!k)deep[v]=0;
			e[i].w-=k;
			e[i^1].w+=k;
			flow+=k;
			sum-=k;
		}
	}
	return flow;
}
signed main(){
	cin>>n;
	s=id(n,n)+n+1,t=s+1;
	for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)cin>>b[i][j];
	for(int i=1;i<=n;i++){
		cin>>c[i];
		add(id(n,n)+i,t,c[i]);
		add(t,id(n,n)+i,0);
		//cout<<id(n,n)+i<<" "<<t<<endl;
	}
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			add(id(i,j),id(n,n)+i,inf);
			add(id(n,n)+i,id(i,j),0);
			add(id(i,j),id(n,n)+j,inf);
			add(id(n,n)+j,id(i,j),0);
			add(s,id(i,j),b[i][j]);
			add(id(i,j),s,0);
			res+=b[i][j];
//			cout<<id(i,j)<<" "<<id(n,n)+i<<endl;
//			cout<<id(i,j)<<" "<<id(n,n)+j<<endl;
//			cout<<s<<" "<<id(i,j)<<endl;
		}
	}
	while(bfs())ans+=dfs(s,inf);
	cout<<res-ans;
	return 0;
}

后记

再写真的要睡过去了……

posted @   小惰惰  阅读(13)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
/* 鼠标点击求赞文字特效 */
点击右上角即可分享
微信分享提示

目录导航