太空飞行计划问题
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; }