CCF201812-5 管道清洁 题解(最小费可行流)

在这里插入图片描述
无源汇的最小费可行流。
需要清洁的管道下界为1,不需要清洁的管道下界为0。
可重复经过的管道上界为正无穷,不可重复经过的管道上界为1。
然后建图直接跑最小费用流。

AC代码:

#include
#include
#include
using namespace std;
const int maxn = 233;
const int inf = 0x3f3f3f3f;
struct node{int u,v,f,w,nxt;node(){};node(int a,int b,int c,int d,int e):u(a),v(b),f(c),w(d),nxt(e){}
}e[maxn*maxn];
int cnt = 0;
int head[maxn];
void add(int u,int v,int f,int w){e[cnt] = node(u,v,f,w,head[u]);head[u] = cnt++;e[cnt] = node(v,u,0,-w,head[v]);head[v] = cnt++;
}
int st,ed,E,ex;
int n,m;
int du[maxn];
int sum;
int num = 0;
void init(){scanf("%d%d",&n,&m);st = 0;ed = n + 1;ex = n + 2;cnt = 0;sum = 0;num = 0;memset(head,-1,ex<<2);memset(du,0,ex<<2);while(m--){int u,v;char c[2];scanf("%d%d%s",&u,&v,c);if(c[0] == 'A'){add(u,v,inf,E);du[u]--;du[v]++;num+=E;}else if(c[0] == 'B'){du[u]--;du[v]++;num+=E;}else if(c[0] == 'C'){add(u,v,inf,E);}else add(u,v,1,E);}for(int i = 1;i <= n;++i){if(du[i] > 0){sum += du[i];add(st,i,du[i],0);}else if(du[i] < 0){add(i,ed,-du[i],0);}}
}
int pre[maxn];
int flow[maxn];
int inq[maxn];
int dis[maxn];
int spfa(){memset(pre,-1,ex<<2);memset(inq,0,ex<<2);memset(dis,0x3f,ex<<2);queue q;q.push(st);flow[st] = inf;inq[st] = 1;dis[st] = 0;while(q.size()){int u = q.front();q.pop();inq[u] = 0;for(int i = head[u];i != -1; i = e[i].nxt){int v = e[i].v;if(e[i].f && dis[v] > dis[u] + e[i].w){dis[v] = dis[u] + e[i].w;pre[v] = i;flow[v] = min(flow[u],e[i].f);if(!inq[v]) inq[v] = 1,q.push(v);}}}if(pre[ed] == -1) return -1;return flow[ed];
}
int mfmv(){int fw = 0;int ans = 0;int d;while((d = spfa())!=-1){fw += d;ans += dis[ed]*d;int v = ed;while(v!=st){e[pre[v]].f -= d;e[pre[v]^1].f += d;v = e[pre[v]].u;}}if(fw!=sum) return -1;return ans + num;
}
void sol(){int ans = mfmv();printf("%d\n",ans);
}
int main(){int T;cin>>T;cin>>E>>E;//输入的S没有用,不管它while(T--){init();sol();}
} 


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部