[最大流] POJ1087 ZOJ1157 A Plug for UNIX
来源:互联网 发布:base64.js 怎么解码 编辑:程序博客网 时间:2024/05/16 08:56
看了几天最大流,还是最喜欢Dinic,比较清晰,下午写了一般预流推进,结构也比较简单,网络流算法真是多。
晚上自己写的第一道网络流,WA了不知道多少次,果然是建图错了,算法没写错,果然网络流建完图就AC一半。
刚开始建图的时候一直把设备的名字无视掉了,以为没用,其实不然。
因为一个设备显然只能插一个插头,所以用设备来连接汇点,中间的各种都要受到最后设备的容量(1)约束,一个设备只能流出1个单位,然后把源点连接到插头,注意插头可能会重复所以用+=1,最后转换器的容量无限大,因为可以无限转换,把转换的连边,这样求最大流才对,还是要学习啊。
贴个代码纪念不易的AC。
ZOJ的输入第一行是测试组数,改一下就行。
#include<map>#include<string>#include<cstring>#include<cstdio>#include<queue>#include<algorithm>#define LL long long in#define INF 0x7fffffffusing namespace std;map<string, int>mp;int mat[1005][1005];int lev[10005];int plu, fac, trans, cnt;int fir[20005], nex[20005];int U[20005], V[20005], ecnt;void add(int a, int b){ U[ecnt] = a, V[ecnt] = b; nex[ecnt] = fir[a]; fir[a] = ecnt ++; U[ecnt] = b, V[ecnt] = a; nex[ecnt] = fir[b]; fir[b] = ecnt++;}bool Bfs(int s,int t){ memset(lev, -1, sizeof(lev)); queue<int>q; q.push(s); lev[s] = 0; while( !q.empty() ){ int u = q.front(); q.pop(); for(int k = fir[u]; k != -1; k = nex[k]){ int v = V[k]; if(mat[u][v] && lev[v] == -1){ lev[v] = lev[u] + 1; q.push(v); } } } return lev[t] > 0;}int Dfs(int s, int t, int low){ if( s == t ) return low; int a = 0; for(int k = fir[s]; k != -1; k = nex[k]){ int v = V[k]; if( mat[s][v] && lev[v] == lev[s] + 1 && (a = Dfs(v, t, min(low, mat[s][v]) ) ) ){ mat[s][v] -= a; mat[v][s] += a; return a; } } lev[s] = -1; return 0;}void Dinic(int s,int t,int n){ int ans = 0, a; while(Bfs(s, t)){ while( a = Dfs(s, t, INF) ) ans += a; } printf("%d\n", fac - ans);}int main(){ int T=0, s = 0, t = 1000; char p[50], p1[50]; //scanf("%d", &T); while(scanf("%d", &plu) != EOF){ int tmp, tmp1; mp.clear(); cnt = 1, ecnt = 0; memset(fir, -1, sizeof(fir)); memset(mat, 0, sizeof(mat)); for(int i = 0; i < plu; ++i){ scanf("%s", p); if( (tmp=mp[p]) == 0) tmp = mp[p] = cnt++; if( !mat[s][tmp] ){ add(s, tmp); } mat[s][tmp] += 1; } scanf("%d%*c", &fac); for(int i = 0; i < fac; ++i){ scanf("%s%s", p1, p); if( (tmp=mp[p]) == 0) tmp = mp[p] = cnt++; if( (tmp1=mp[p1]) == 0) tmp1 = mp[p1] = cnt++; mat[tmp1][tmp] += 1; mat[tmp][t] += 1; add(tmp1, tmp); add(tmp, t); } scanf("%d%*c", &trans); for(int i = 0; i < trans; ++i){ scanf("%s%s", p, p1); if( (tmp=mp[p]) == 0) tmp = mp[p] = cnt++; if( (tmp1=mp[p1]) == 0 ) tmp1 = mp[p1] = cnt++; mat[tmp1][tmp] = INF; add(tmp1, tmp); } Dinic(s, t, cnt); }}
再贴一个一般预流推进,顺便写了一发熟悉算法结构。
#include<map>#include<string>#include<cstring>#include<cstdio>#include<queue>#include<algorithm>#define LL long long in#define INF 0x7fffffffusing namespace std;map<string, int>mp;int mat[1005][1005];int plu, fac, trans, cnt;int fir[20005], nex[20005];int U[20005], V[20005], ecnt;int dis[1005], ef[1005]; //距离标号 盈余queue<int>q;void add(int a, int b){ U[ecnt] = a, V[ecnt] = b; nex[ecnt] = fir[a]; fir[a] = ecnt ++; U[ecnt] = b, V[ecnt] = a; nex[ecnt] = fir[b]; fir[b] = ecnt++;}void push(int s, int t, int u,int &ans){ int v, p; for(int k = fir[u]; k != -1; k = nex[k]){ v = V[k], p = min(mat[u][v], ef[u]); if( p && (u == s || dis[u] == dis[v] + 1)){ mat[u][v] -= p, mat[v][u] += p; ef[u] -= p, ef[v] += p; if( v == t) ans += p; if( v != s && v!=t ) q.push(v); } }}void relabel(int s, int t, int u){ if(u != s && u != t && ef[u]){ dis[u]+=1; q.push(u); }}void push_relabel(int s, int t, int n){ int ans = 0; memset(dis, 0, sizeof(dis)); dis[s] = n; ef[s] = INF, ef[t] = -INF; q.push(s); int u; while(!q.empty()){ u = q.front(); q.pop(); push(s, t, u, ans); relabel(s, t, u); } printf("%d\n", fac - ans);}int main(){ int T=0, s = 0, t = 1000; char p[50], p1[50]; while( scanf("%d", &plu) != EOF ){ int tmp, tmp1; mp.clear(); cnt = 1, ecnt = 0; memset(fir, -1, sizeof(fir)); memset(mat, 0, sizeof(mat)); for(int i = 0; i < plu; ++i){ scanf("%s", p); if( (tmp=mp[p]) == 0) tmp = mp[p] = cnt++; if( !mat[s][tmp] ){ add(s, tmp); } mat[s][tmp] += 1; } scanf("%d%*c", &fac); for(int i = 0; i < fac; ++i){ scanf("%s%s", p1, p); if( (tmp=mp[p]) == 0) tmp = mp[p] = cnt++; if( (tmp1=mp[p1]) == 0) tmp1 = mp[p1] = cnt++; mat[tmp1][tmp] += 1; mat[tmp][t] += 1; add(tmp1, tmp); add(tmp, t); } scanf("%d%*c", &trans); for(int i = 0; i < trans; ++i){ scanf("%s%s", p, p1); if( (tmp=mp[p]) == 0) tmp = mp[p] = cnt++; if( (tmp1=mp[p1]) == 0 ) tmp1 = mp[p1] = cnt++; mat[tmp1][tmp] = INF; add(tmp1, tmp); } push_relabel(s, t, cnt); if(T) puts(""); }}
0 0
- [最大流] POJ1087 ZOJ1157 A Plug for UNIX
- ZOJ1157, POJ1087,UVA 753 A Plug for UNIX (最大流)
- POJ1087 A Plug for UNIX 【最大流】
- poj1087 A Plug for UNIX (最大流)
- POJ1087 A Plug for UNIX(最大流)
- poj1087 A Plug for UNIX 最大流
- poj1087 A Plug for UNIX(最大流)
- POJ1087 A Plug for UNIX(map+dinic最大流)
- POJ1087:A Plug for UNIX(最大流)
- poj1087&hdu1526A Plug for UNIX(最大流)
- 【网络流】:poj1087,A Plug for UNIX
- poj1087 - A Plug for UNIX
- poj1087 A Plug for UNIX
- POJ1087--A Plug for UNIX
- poj1087 A Plug for UNIX
- POJ1087 A Plug for UNIX
- POJ1087 A Plug for UNIX
- POJ1087-A Plug for UNIX
- iTOP4412环境搭建:arm-linux-gcc: 没有那个文件或目录
- sap screen design
- Hive 知识盲点
- 杭电1001
- ubuntu下一些常见问题的解决方式
- [最大流] POJ1087 ZOJ1157 A Plug for UNIX
- ceph高级命令
- 凯云水利水电工程造价系统 (六)中间单价(2)
- [BZOJ3932]CQOI2015任务查询系统|主席树
- tomcat下web应用http访问自动跳转为https形式访问
- android使用ant自动打包(包括更改文件中的内容)
- 在VS2008中移植uCOS-II
- Spring2.5学习3.1_用@Resource注解完成属性装配
- 会员卡管理系统技术解析(十四)添加会员卡换卡记录