原题地址:http://acm.hdu.edu.cn/showproblem.php?pid=1532
关于利用vector建图的一些理解
e[u].push_back((edge){v,w,e[v].size()});
e[v].push_back((edge){u,0,e[u].size()-1});
/*
先声明struct edge{
int to,cap,rev;//分别表示终点,容量,反向边
}
就比如说是第1条,说明从v连向u的边是G[v]中的第e[v].size()条
*/
下面是利用前向星建的图
#include <cmath>
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <queue>
#include <vector>
#include <stack>
#include <set>
#include <cctype>
#define eps 1e-8
#define INF 0x3f3f3f3f
#define MOD 1e9+7
#define PI acos(-1)
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define CLR(x,y) memset((x),y,sizeof(x))
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 1e5 + 5;
struct edge {//前向星
int v, nxt, w;
}edge[maxn];
struct node {
int v, id;
}pre[maxn];
int n, m, cnt;
int head[maxn];
void init() {
cnt = 0;
memset(edge, 0, sizeof(edge));
memset(head, -1, sizeof(head));
}
void add_edge(int u, int v, int w) {
edge[cnt].v = v;
edge[cnt].w = w;
edge[cnt].nxt = head[u];
head[u] = cnt++;
}
bool vis[maxn];
bool bfs(int s, int t) {//bfs寻找增广路
queue<int>q;
memset(vis, 0, sizeof(vis));
memset(pre, -1, sizeof(pre));
pre[s].v = s;
vis[s] = true;
q.push(s);
while(!q.empty()) {
int u = q.front();
q.pop();
for(int i = head[u]; ~i; i = edge[i].nxt) {
int v = edge[i].v;
if(!vis[v] && edge[i].w) {
pre[v].v = u;//v的前驱节点是u,第2个v是前驱节点的意思
pre[v].id = i;//v的前驱节点的线段编号是i
//这条边是连接u和v的边
vis[v] = true;
if(v == t) return true;
q.push(v);
}
}
}
return false;
}
int EK(int s, int t) {
int ans = 0;
while(bfs(s, t)) {
int mi = INF;
for(int i = t; i != s; i = pre[i].v) {
mi = min(mi, edge[pre[i].id].w);//每次寻找在bfs过程中当前可以使用的最少的流量
}
for(int i = t; i != s; i = pre[i].v) {
//pre数组其实就是i记录了当前bfs寻找增广路的路径,从终点开始倒着寻找
edge[pre[i].id].w -= mi;//正向边--
edge[pre[i].id ^ 1].w += mi;//反向边++
//因为建边的时候是相邻的,所以可以利用^1得到反向边的id
}
ans += mi;
}
return ans;
}
int main() {
while(~scanf("%d%d", &m, &n)) {
init();
for(int i = 1; i <= m; i++) {
int u, v, w;
scanf("%d%d%d", &u, &v, &w);
add_edge(u, v, w);//正向建边
add_edge(v, u, 0);//反向建权值为0的边
}
int ans = EK(1, n);
printf("%d\n", ans);
}
return 0;
}
下面是vector建图的,网上找的,还没转化为自己的板子
#include<stdio.h>
#include<string.h>
#include<vector>
#define maxn 222
#define inf 0x3f3f3f3f
using namespace std;
struct edge{
int to;
int cap;
int rev;
};
vector<edge>e[maxn];
int book[maxn];
int dfs(int cur,int end,int flow){
if(cur == end)
return flow;
book[cur] = 1;
for(int i = 0;i<e[cur].size();i++){
edge &temp = e[cur][i];
if(!book[temp.to] && temp.cap>0){
int d = dfs(temp.to,end,min(flow,temp.cap));
if(d > 0){
temp.cap -= d;
e[temp.to][temp.rev].cap += d;
return d;
}
}
}
return 0;
}
int main(){
int n,m;
while(scanf("%d%d",&n,&m)!=EOF){
for(int i = 1;i<=n;i++)
e[i].clear();
int u,v,w;
for(int i = 0;i<n;i++){
scanf("%d%d%d",&u,&v,&w);
e[u].push_back((edge){v,w,e[v].size()});
e[v].push_back((edge){u,0,e[u].size()-1});
}
int ans = 0;
while(1){
memset(book,0,sizeof(book));
int temp = dfs(1,m,inf);
if(temp == 0)
break;
ans += temp;
}
printf("%d\n",ans);
}
return 0;
}
邻接矩阵版本
#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
const int MAXN = 300;
const int MAX_INT = ((1 << 31) - 1);
int n; // 图中点的数目
int pre[MAXN]; // 从 s - t 中的一个可行流中, 节点 i 的前序节点为 Pre[i];
bool vis[MAXN]; // 标记一个点是否被访问过
int mp[MAXN][MAXN]; // 记录图信息
bool bfs(int s, int t){
queue <int> que;
memset(vis, 0, sizeof(vis));
memset(pre, -1, sizeof(pre));
pre[s] = s;
vis[s] = true;
que.push(s);
while(!que.empty()){
int u = que.front();
que.pop();
for(int i = 1; i <= n; i++){
if(mp[u][i] && !vis[i]){
pre[i] = u;
vis[i] = true;
if(i == t) return true;
que.push(i);
}
}
}
return false;
}
int EK(int s, int t){
int ans = 0;
while(bfs(s, t)){
int mi = MAX_INT;
for(int i = t; i != s; i = pre[i]){
mi = min(mi, mp[pre[i]][i]);
}
for(int i = t; i != s; i = pre[i]){
mp[pre[i]][i] -= mi;
mp[i][pre[i]] += mi;
}
ans += mi;
}
return ans;
}