题目链接:http://acm.hit.edu.cn/hoj/problem/view?id=1228
http://poj.org/problem?id=1459
本题是练习网络流的模板题。
按照BFS求最大流即可。另开两个节点做超级起始点和超级终结点。
Poj一遍过,为啥Hoj用Scanf读数据会超时,改成Cin就A了,无语。
先写增广路算法。
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;
#define Maxn 105
#define INF 1<<30
vector<int> node[Maxn];
//容量
int cap[Maxn][Maxn];
//流量
int flow[Maxn][Maxn];
//起始点到当前节点的最小残量
int a[Maxn];
//记录父亲节点
int p[Maxn];
void init()
{
for(int i=0; i<Maxn; i++)
{
node[i].clear();
}
}
int edmondsKarp(int s,int t)
{
//最大流值
int f = 0;
queue<int> q;
memset(flow,0,sizeof(flow));
for(;;)
{
memset(a,0,sizeof(a));
a[s] = INF;
q.push(s);
while(!q.empty())
{
int u = q.front();
q.pop();
int size = node[u].size();
for(int i=0; i<size; i++)
{
int v = node[u][i];
if(cap[u][v]>flow[u][v] && !a[v])
{
a[v] = a[u] < cap[u][v] - flow[u][v] ? a[u] : cap[u][v] - flow[u][v];
p[v] = u;
q.push(v);
}
}
}
if(a[t] == 0) return f;
for(int u = t; u!=s; u=p[u])
{
flow[p[u]][u] += a[t];
flow[u][p[u]] -= a[t];
}
f += a[t];
}
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif
int n,np,nc,m;
int u,v,z;
int s,t;
while(cin>>n>>np>>nc>>m)
//为什么HOJ改成scanf会超时?
//while(scanf(" %d %d %d %d",&n,&np,&nc,&m)!=EOF)
{
init();
for(int i=0; i<m; i++)
{
scanf(" (%d,%d)%d",&u,&v,&z);
if(u!=v)
{
cap[u][v] = z;
node[u].push_back(v);
}
}
//建立超级起始点和超级终结点
s = n,t = n+1;
for(int i=0; i<np; i++)
{
scanf(" (%d)%d",&u,&z);
cap[s][u] = z;
node[s].push_back(u);
}
for(int i=0; i<nc; i++)
{
scanf(" (%d)%d",&u,&z);
cap[u][t] = z;
node[u].push_back(t);
}
printf("%d\n",edmondsKarp(s,t));
}
return 0;
}
补充一下Dicnic算法,这种情况一定要插入两条边,第二条边的cap为0。
果然快不少:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <stack>
#include <queue>
#include <algorithm>
#include <iostream>
using namespace std;
#define Maxn 105
#define Maxm 400005
#define INF 1<<30
struct Edge
{
int a,b;
int cap,flow;
};
struct Dicnic
{
Edge edge[Maxm];
int first[Maxn];
int next[Maxm];
int total;
int s,t;
int vis[Maxn],d[Maxn],cur[Maxn];
void init()
{
total = 0;
memset(first,-1,sizeof(first));
}
void addEdge(int a,int b,int w)
{
edge[total].a = a,edge[total].b = b,edge[total].cap = w;
edge[total].flow = 0;
next[total] = first[a];
first[a] = total++;
}
bool bfs()
{
memset(vis,0,sizeof(vis));
queue <int> q;
q.push(s);
vis[s] = 1;
d[s] = 0;
while(!q.empty())
{
int x = q.front();
q.pop();
for(int i=first[x];i!=-1;i=next[i])
{
int y = edge[i].b;
if(!vis[y] && edge[i].cap > edge[i].flow)
{
vis[y] = 1;
d[y] = d[x] + 1;
q.push(y);
}
}
}
return vis[t];
}
int dfs(int x,int a)
{
if(x == t || a == 0) return a;
int flow = 0;
int f;
for(int &i = cur[x];i!=-1;i=next[i])
{
Edge &e = edge[i];
if(d[x] + 1 == d[e.b])
{
f = dfs(e.b,min(a,e.cap - e.flow));
if(f > 0)
{
e.flow += f;
edge[i^1].flow -= f;
flow += f;
a -= f;
if(a == 0) break;
}
}
}
return flow;
}
int maxFlow(int s,int t)
{
this->s = s,this->t = t;
int flow = 0;
while(bfs())
{
memcpy(cur,first,sizeof(first));
flow += dfs(s,INF);
}
return flow;
}
}dicnic;
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif
int n,np,nc,m;
int u,v,z;
int s,t;
while(cin>>n>>np>>nc>>m)
//while(scanf(" %d %d %d %d",&n,&np,&nc,&m)!=EOF)
{
dicnic.init();
for(int i=0; i<m; i++)
{
scanf(" (%d,%d)%d",&u,&v,&z);
if(u!=v)
{
dicnic.addEdge(u,v,z);
dicnic.addEdge(v,u,0);
}
}
//建立超级起始点和超级终结点
s = n,t = n+1;
for(int i=0; i<np; i++)
{
scanf(" (%d)%d",&u,&z);
dicnic.addEdge(s,u,z);
dicnic.addEdge(u,s,0);
//cap[s][u] = z;
//node[s].push_back(u);
}
for(int i=0; i<nc; i++)
{
scanf(" (%d)%d",&u,&z);
dicnic.addEdge(u,t,z);
dicnic.addEdge(t,u,0);
//cap[u][t] = z;
//node[u].push_back(t);
}
//printf("%d\n",edmondsKarp(s,t));
printf("%d\n",dicnic.maxFlow(s,t));
}
return 0;
}
再补充一下ISAP解法:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <stack>
#include <queue>
#include <algorithm>
#include <iostream>
using namespace std;
#define Maxn 105
#define Maxm 400005
#define INF 1<<30
struct Edge
{
int a,b;
int cap,flow;
};
struct ISAP
{
Edge edge[Maxm];
int first[Maxn];
int next[Maxm];
int total;
int s,t;
int n;
int vis[Maxn],d[Maxn],cur[Maxn];
int num[Maxn],p[Maxn];
void init()
{
total = 0;
memset(first,-1,sizeof(first));
}
void initn(int n)
{
this->n = n;
}
//记着增加反向边
void addEdge(int a,int b,int w)
{
edge[total].a = a,edge[total].b = b,edge[total].cap = w;
edge[total].flow = 0;
next[total] = first[a];
first[a] = total++;
}
bool bfs()
{
memset(vis,0,sizeof(vis));
queue <int> q;
q.push(t);
vis[t] = 1;
d[t] = 0;
while(!q.empty())
{
int x = q.front();
q.pop();
for(int i=first[x];i!=-1;i=next[i])
{
Edge &e = edge[i^1];
if(!vis[e.a] && e.cap>e.flow)
{
vis[e.a] = 1;
d[e.a] = d[x] + 1;
q.push(e.a);
}
}
}
return vis[s];
}
int Augment()
{
int x = t,a = INF;
while(x!=s)
{
Edge &e = edge[p[x]];
a = min(a,e.cap - e.flow);
x = edge[p[x]].a;
}
x = t;
while(x!=s)
{
edge[p[x]].flow += a;
edge[p[x]^1].flow -= a;
x = edge[p[x]].a;
}
return a;
}
int maxFlow(int s,int t)
{
this->s = s,this->t = t;
int flow = 0;
bfs();
memset(num,0,sizeof(num));
for(int i=0;i<n;i++)
{
num[d[i]]++;
}
int x = s;
memcpy(cur,first,sizeof(first));
while(d[s] < n)
{
if(x == t)
{
flow += Augment();
x = s;
}
int ok = 0;
for(int i=cur[x];i!=-1;i=next[i])
{
Edge &e = edge[i];
if(e.cap > e.flow && d[x] == d[e.b] + 1)
{
ok = 1;
p[e.b] = i;
cur[x] = i;
x = e.b;
break;
}
}
if(!ok)
{
int m = n-1;
for(int i=first[x];i!=-1;i=next[i])
{
Edge &e = edge[i];
if(e.cap > e.flow) m = min(m,d[e.b]);
}
if(--num[d[x]] == 0) break;
num[d[x] = m+1]++;
cur[x] = first[x];
if(x!=s) x = edge[p[x]].a;
}
}
return flow;
}
}isap;
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif
int n,np,nc,m;
int u,v,z;
int s,t;
while(cin>>n>>np>>nc>>m)
//while(scanf(" %d %d %d %d",&n,&np,&nc,&m)!=EOF)
{
isap.init();
for(int i=0; i<m; i++)
{
scanf(" (%d,%d)%d",&u,&v,&z);
if(u!=v)
{
isap.addEdge(u,v,z);
isap.addEdge(v,u,0);
}
}
//建立超级起始点和超级终结点
s = n,t = n+1;
for(int i=0; i<np; i++)
{
scanf(" (%d)%d",&u,&z);
isap.addEdge(s,u,z);
isap.addEdge(u,s,0);
//cap[s][u] = z;
//node[s].push_back(u);
}
for(int i=0; i<nc; i++)
{
scanf(" (%d)%d",&u,&z);
isap.addEdge(u,t,z);
isap.addEdge(t,u,0);
//cap[u][t] = z;
//node[u].push_back(t);
}
isap.initn(n+2);
//printf("%d\n",edmondsKarp(s,t));
printf("%d\n",isap.maxFlow(s,t));
}
return 0;
}