http://www.wikioi.com/problem/1233/
网络流最小费用问题
一开始看这个人的博客:
http://blog.sina.com.cn/s/blog_61034ad90100eine.html,写了4天了,还是没能写出自己的代码。。。
后面面还有在这个OJ上AC了的代码。
照着这个人的代码打,还是没能想明白。。这个代码和这个OJ上的不同,是简化问题了的。只求最大收益
照着打的代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#define INF 999999
using namespace std;
//分别为残余网络,返回值,当前枚举的点,当前点的前驱,当前点到汇点的距离,距离为I的点数
int a[500][500],fh[500],now[500],pre[500],dis[500],sumd[500];
int n,m,ans; //仪器数,实验数,收入
queue<int> q;
void cl()
{
ans = 0;
memset(a,0,sizeof(a));
memset(fh,0,sizeof(fh));
memset(now,0,sizeof(now));
memset(pre,0,sizeof(pre));
memset(dis,0,sizeof(dis));
memset(sumd,0,sizeof(sumd));
return ;
}
void input()
{
int i,j,p;
for(i = 1; i <= m; i++)
{
scanf("%d",&a[0][i]); //原点为0第t个实验的收益
ans+=a[0][i]; //累加收入
while(scanf("%d",&p)&&p)
{
a[i][p+m] = INF; //每个实验所需的实验仪器,t为实验编号,p为所需仪器编号
}
}
for(i = m+1; i <= n+m; i++)
{
scanf("%d",&a[i][n+m+1]); //每个实验器材的成本,汇点为n+m
}
n = m+n+1; //汇聚点更改
return ;
}
void sap()
{
int i,j,k,flow,minn;
bool flag;
sumd[0] = n+1;
i = 0;
flow = INF;
while(dis[0] < n)
{
fh[i] = flow; //保存返回值
flag = false;
for(j = now[i]; j <= n; j++)
{
if(a[i][j] > 0 && dis[i] == dis[j]) //满足有边,且距离之差为1
{
now[i] = j; //更新访问节点
flag = true;
if(a[i][j]<flow)//更改该路上可通行的流量
{
flow = a[i][j];
}
pre[j] = i;//记录前驱
i = j;
if(i == n)
{
ans-=flow; //减去这个流量
while(i!=0)
{
k = pre[i];
a[k][i]-=flow;
a[i][k]+=flow;
i = k;
}
}
break;
}
}
if(flag)
{
continue; //找不到增广路,不修改
}
minn = n+1; //赋值为最大距离
for(j = 0; j<=n; j++)
{
if(a[i][j]>0&&dis[j]<minn)
{
minn = dis[j]; //找到最小距离的点
now[i] = j; //更新前驱
}
}
sumd[dis[i]]--; //到该距离的总点数减一
if(sumd[dis[i]]==0) break;//中间没有点,有断层,无法找到增广路
dis[i] = minn+1; //距离加一
sumd[dis[i]]++; //到该距离的总点数加一
if(i!=0)
{
i = pre[i]; //当前状态以改变,返回上一层
flow = fh[i];
}
}
printf("%d\n",ans);
return ;
}
int main()
{
while(scanf("%d%d",&m,&n)!=EOF)
{
cl();//初始化清空
input();//输入数据
/*for(int i=0; i<=m+n;i++)
{
for(int j=0; j<=m+n;j++)
{
printf("%6d ",a[i][j]);
}
printf("\n");
}*/
sap();
}
return 0;
}
在这个OJ网站上下的别人AC代码,慢慢看把。。T_T。。
代码:
#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
#include<iostream>
#define MAXL 1010
#define MAXN 100010
#define MAXM 1000010
#define oo 0x7FFFFFFF
using namespace std;
int first[MAXN], next[MAXM], v[MAXM], cost[MAXM], e;
int n;
int src, des;
bool flag;
bool vis[MAXL];
char str[MAXN];
vector<int> g[MAXL];
vector<int> test;
vector<int> app;
int a[MAXL];
inline void addEdge(int x, int y, int val)
{
v[e] = y;
cost[e] = val;
next[e] = first[x];
first[x] = e++;
v[e] = x;
cost[e] = 0;
next[e] = first[y];
first[y] = e++;
}
int SAP()
{
int pre[MAXN], cur[MAXN], dis[MAXN], gap[MAXN];
int flow = 0;
int aug = oo;
int x, y;
bool flag;
for (int i = 0; i < n; i++)
{
cur[i] = first[i];
gap[i] = dis[i] = 0;
}
gap[src] = n;
x = pre[src] = src;
while (dis[src] < n)
{
flag = false;
for (int &j = cur[x]; j != -1; j = next[j])
{
y = v[j];
if (cost[j] > 0 && dis[x] == dis[y] + 1)
{
flag = true;
aug = min(aug, cost[j]);
pre[y] = x;
x = y;
if (x == des)
{
flow += aug;
while (x != src)
{
x = pre[x];
cost[cur[x]] -= aug;
cost[cur[x] ^ 1] += aug;
}
aug = oo;
}
break;
}
}
if (flag)
{
continue;
}
int tmp = n;
for (int j = first[x]; j != -1; j = next[j])
{
y = v[j];
if (cost[j] > 0 && dis[y] < tmp)
{
tmp = dis[y];
cur[x] = j;
}
}
if ((--gap[dis[x]]) == 0)
{
break;
}
gap[dis[x] = tmp + 1]++;
x = pre[x];
}
return flow;
}
void out(vector<int> res)
{
int i;
sort(res.begin(), res.end());
res.resize(unique(res.begin(), res.end()) - res.begin());
for (i = 0; i < (int) res.size(); i++)
{
if (i)
{
putchar(' ');
}
printf("%d", res[i]);
}
putchar('\n');
}
void dfs(int x)
{
int i;
vis[x] = true;
if (x == des)
{
flag = false;
}
for (i = first[x]; i != -1; i = next[i])
{
if (!vis[v[i]] && cost[i] > 0)
{
dfs(v[i]);
}
}
}
int main()
{
int m;
int i, j, k;
int len;
int ans;
while (~scanf("%d%d", &m, &n))
{
src = 0;
des = n + m + 1;
e = 0;
memset(first, -1, sizeof(first));
gets(str);
for (i = 1; i <= m; i++)
{
g[i].clear();
gets(str);
len = strlen(str);
for (j = 0; j < len; j++)
{
for (; j < len && str[j] == ' '; j++);
if (j < len)
{
sscanf(str + j, "%d", &k);
g[i].push_back(k);
}
for (; j < len && isdigit(str[j]); j++)
;
}
}
for (i = 1; i <= n; i++)
{
scanf("%d", &a[i]);
addEdge(m + i, des, a[i]);
}
ans = 0;
for (i = 1; i <= m; i++)
{
addEdge(src, i, g[i][0]);
ans += g[i][0];
for (j = 1; j < (int) g[i].size(); j++)
{
addEdge(i, m + g[i][j], oo);
}
}
n = des + 1;
ans -= SAP();
test.clear();
app.clear();
for (i = first[src]; i != -1; i = next[i])
{
k = v[i];
flag = true;
memset(vis, false, sizeof(vis));
dfs(k);
if (flag)
{
test.push_back(k);
for (j = 1; j < (int) g[k].size(); j++)
{
app.push_back(g[k][j]);
}
}
}
out(test);
out(app);
printf("%d\n", ans);
}
return 0;
}