CF843E Maximum Flow

考虑到最小割一定是满流,此时最小割边数就是答案。

对于 \(g_i=0\),连接 \((u_i,v_i,inf)\),没有流量则一定可以走到,还需要防止隔断;对于 \(g_i=1\),连接 \((u_i,v_i,1),(v_i,u_i,inf)\),该边有流量则反向边一定有残余容量,且如果没满流,那么 \(u_i\) 可以到达 \(v_i\),否则就选择它假如最小割并认为它满流。

对于方案,直接上下界网络流跑有流边的方案,也就是下界为 \(1\),上界为 \(inf\),此时每条边的流量就是它此时的流量(注意加上下界),如果它是我们选定的最小割,则容量为它流量,否则为 \(inf\)

#include<bits/stdc++.h>
using namespace std;
int n,m,s,t,tot=1,flow,maxflow,es[1001],a[1001],b[1001],g[1001],vis[301],dep[301],head[301],now[301],nex[30001],edge[30001],ver[30001];
queue <int> q;
void add(int u,int v,int w){
    ver[++tot]=v,edge[tot]=w,nex[tot]=head[u],head[u]=tot;
    ver[++tot]=u,edge[tot]=0,nex[tot]=head[v],head[v]=tot;
}
bool bfs(){
    memset(dep,0,sizeof(dep));
    while(q.size()) q.pop();
    q.push(s);
    dep[s]=1;
    while(q.size()){
        int x=q.front();
        q.pop();
        for(int i=head[x];i;i=nex[i]){
            if(edge[i]&&!dep[ver[i]]){
                q.push(ver[i]);
                dep[ver[i]]=dep[x]+1;
                if(ver[i]==t) return true;
            }
        }
    }
    return false;
}
int dinic(int x,int flow){
    if(x==t) return flow;
    int rest=flow,k;
    for(int i=now[x];i&&rest;i=nex[i]){
        now[x]=i;
        if(edge[i]&&dep[ver[i]]==dep[x]+1){
            k=dinic(ver[i],min(edge[i],rest));
            if(!k) dep[ver[i]]=0;
            rest-=k;
            edge[i]-=k;
            edge[i^1]+=k;
        }
    }
    return flow-rest;
}
void dfs(int x){
	vis[x]=1;
	for(int i=head[x];i;i=nex[i]) if(!vis[ver[i]]&&edge[i]) dfs(ver[i]);
}
int main(){
	scanf("%d%d%d%d",&n,&m,&s,&t);
	for(int i=1;i<=m;i++){
		scanf("%d%d%d",&a[i],&b[i],&g[i]);
		if(g[i]) add(a[i],b[i],1),add(b[i],a[i],1e6);
		else add(a[i],b[i],1e6);
	}
	while(bfs()){
		for(int i=1;i<=n;i++) now[i]=head[i];
		while(flow=dinic(s,1e6)) maxflow+=flow;
	}
	dfs(s);
	printf("%d\n",maxflow);
	for(int i=1;i<=n;i++) head[i]=maxflow=0,tot=1;
	add(t,s,1e6);
	s=0,t=n+1;
	for(int i=1;i<=m;i++){
		if(g[i]){
			add(a[i],b[i],(1e6-1));
			add(s,b[i],1);
			add(a[i],t,1);
			es[i]=tot-4;
		}
	}
	while(bfs()){
		for(int i=0;i<=n+1;i++) now[i]=head[i];
		while(flow=dinic(s,1e6)) maxflow+=flow;
	}
	for(int i=1;i<=m;i++){
		if(g[i]){
			if(vis[a[i]]!=vis[b[i]]) printf("%d %d\n",edge[es[i]]+1,edge[es[i]]+1);
			else printf("%d 1000000\n",edge[es[i]]+1);
		}
		else printf("0 1000000\n");
	}
	return 0;
}
posted @ 2024-07-28 11:46  zyxawa  阅读(11)  评论(0)    收藏  举报