POJ 1087
来源:互联网 发布:lol显示网络不稳定 编辑:程序博客网 时间:2024/05/03 01:49
这是一个 网络中的最大流问题的 经典问题。
题目:
有n个插座,m个电器,k种适配器(a,b),表示插座b可以替代插座a
问最少有多少个 电器 充不到电?
这道题 可以转换为 求最多可以多少个 电器设备可插入? maxflow
那么问题的答案就是 m - maxflow
下面就是 如何求最大流 maxflow.
增广路算法:每次用BFS找一条最短的增广路径,然后沿着这条路径修改流量值(实际修改的是残量网络的边权)。当没有增广路时,算法停止,此时的流就是最大流。
增广路 就是 一条 从源点到汇点的 一条路径。
什么是源点,什么是汇点?
在本题中,建立两个点source,sink,分别表示 源点与汇点,source点分别指向 各个 电器设备,权值为1,表示只有一个电器设备。然后将 各个电器设备 指向各自能插的 插座,权值为1,表示一个电器设备只能 插一个 插座。然后将 插座 与 可以转换的 插座相连,权值为 MAX,表示可以有无数个转换器。最后将 可以进行转换的插座 连向汇点。
问题要求的是,从源点 到 汇点 的 最大流。
#include <iostream>#include <map>#include <string>#include <queue>using namespace std;#define MAXV 500#define MAX 1<<29#define min(a,b) ((a)<(b)?(a):(b))map<string,int> rec_dev; // 给每一个设备或者插座 一个标号,键值为0表示为新边char str[30],stmp[30];int rec_dev_sum; //设备的编号int res[MAXV][MAXV]; // 构建的图,G=(V,E),res[i][j]表示第i点到第j点int n,m,k;int dis[MAXV];int source,sink,maxflow; //分别表示 源点、汇点、最大流int bfs(){ int k,i; queue<int> q; memset(dis,-1,sizeof(dis)); //dis数组为标记数组,-1表示未访问 dis[sink] = 0; //从汇点开始,搜索 q.push(sink); while(!q.empty()){ k = q.front(); q.pop(); for(i=0;i<MAXV;i++){ if(dis[i]==-1&&res[i][k]){ //该点未访问过 且 第i点到第k点可达 dis[i] = dis[k] + 1; q.push(i); } } if(k == source) return 1; } return 0;}int dfs(int cur,int cp){ if(cur == sink) return cp; int temp = cp,t; for(int i=0;i<MAXV&&temp;i++){ if(dis[i]+1 == dis[cur] && res[cur][i]){ t = dfs(i,min(res[cur][i],temp)); res[cur][i] -= t; res[i][cur] += t; temp -= t; } } return cp-temp;}void dinic(){ maxflow = 0; //初始化 while(bfs()) //如果存在增广路 maxflow += dfs(source,MAX);}int main(){ int i; while(cin>>n){ memset(res,0,sizeof(res)); rec_dev.clear(); rec_dev_sum = 1; //标号从1开始,0用来表示 源点Source source = 0; sink = MAXV - 1; for(i=0;i<n;i++){ cin>>str; rec_dev[str] = rec_dev_sum++; res[rec_dev[str]][sink] = 1; //插座到汇点的值为1 } cin>>m; for(i=0;i<m;i++){ cin>>stmp>>str; rec_dev[stmp] = rec_dev_sum++; //给电器设备编号 if(!rec_dev[str]) //表示这是一个新的插座,加入新边 rec_dev[str] = rec_dev_sum++; res[source][rec_dev[stmp]] = 1; //源点到电器设备的值为1 res[rec_dev[stmp]][rec_dev[str]] = 1; //电器设备到插座的值为1 } cin>>k; for(i=0;i<k;i++){ cin>>str>>stmp; if(!rec_dev[str]) //表示这是一个新的插座,加入新边 rec_dev[str] = rec_dev_sum ++; if(!rec_dev[stmp]) rec_dev[stmp] = rec_dev_sum ++; res[rec_dev[str]][rec_dev[stmp]] = MAX; //转换器 有无数个,所以 值为无穷大 } dinic(); //求最大流算法 cout<<m-maxflow; //电器设备总量 - 最大可以充电的设备 = 没有充电的设备 } return 0;}
0 0
- POJ 1087
- poj 1087
- poj-1087
- POJ 1087
- poj 1087
- poj 1087
- POJ 1087
- poj 1087 解题报告
- poj 1087(最大流)
- poj 1087 最大流
- poj 1087 网络流
- POJ 1087 UNIX dinic
- poj 1087 (最大流)
- POJ 1087最大流
- POJ 1087 网络流
- POJ
- poj
- POJ
- 在LaTeX中插入美观的Matlab代码
- 第39讲项目3——反序数(改)
- java.io.Serializable的作用
- SQL语句大全
- jQuery的学习笔记
- POJ 1087
- Git 远程操作
- hdu5645(基础)
- 从网上获取一个网页,在一个TextView中将其源代码显示出来
- 智能维护系统的算法s
- Cococs2d-x SimpleAudioEngine播放背景音乐
- Android 设计模式 之 单例模式
- android之SharedPreferences
- javaScript的基础学习