wikioi1033 蚯蚓的游戏问题
2014-06-09 19:13
302 查看
第一次写网络流的拆点问题,本题可以把一个点拆成两个点,一个进,一个出,其标号分别用getnum()和getnum2()求出。至于为什么要拆点,这个问题我一开始纠结了很久,其实道理很简单,由题意知每个点只能经过一次,而最大流的基础写法里没有考虑这个问题,于是我们要将每个点拆分一下,用拆成的两个点记录流量。总起点和第一行的每一个点的起点连一个价值为0,流量为1的边(只能走一次),初始图里的点之间的连接就用 起点的出点 与 终点的入点 连一条价值为0,流量为1的边(只能走一次)。最后把最后一行的所有出点与 总终点相连即可。我的代码中t为总终点,0为总起点。
#include <cstdio> #include <queue> #include <cstring> #include <algorithm> #include <cmath> using namespace std; #define MAXN 1100000 #define MAXM 1100000 #define INF 0x3f3f3f3f struct node { int u,v,f,c,next; }e[MAXM]; int mat[1100][1100]; int k,head[MAXN],pre[MAXN],dist[MAXN],vis[MAXN]; int en,s,t,maxflow,mincost,m,n; //s源点,t汇点 void add(int u,int v,int c,int f) { e[en].u=u; e[en].v=v; e[en].c=c; e[en].f=f; e[en].next=head[u]; head[u]=en++; } int spfa() { int i,u,v; for(i=0;i<=t;i++) pre[i]=-1,vis[i]=0,dist[i]=INF; dist[s]=0; vis[s]=1; queue<int>q; q.push(s); while(!q.empty()) { u=q.front(); q.pop(); for(i=head[u];i!=-1;i=e[i].next) { v=e[i].v; if(e[i].f>0&&dist[u]+e[i].c<dist[v]) { dist[v]=dist[u]+e[i].c; pre[v]=i; if(!vis[v]) { vis[v]=1; q.push(v); } } } vis[u]=0; } if(dist[t]==INF) return 0; return 1; } void add() { int v; int maxf=INF; for(v=pre[t];e[v].u!=s;v=pre[e[v].u]) maxf=min(maxf,e[v].f); for(v=pre[t];e[v].u!=s;v=pre[e[v].u]) { e[v].f-=maxf; e[v^1].f+=maxf; maxflow+=maxf; mincost+=maxf*e[v].c; } } int getnum(int x,int y) { return (x-1)*(2*m+x-2)/2+y; } int getnum2(int x,int y) { return (x-1)*(2*m+x-2)/2+y+n*(2*m+n-1)/2; } void init() { maxflow=0; s=0; t=getnum2(n,m+n-1)+1; en=0; memset(head,-1,sizeof(head)); } int main() { int i,j,a,b,c; scanf("%d%d%d",&n,&m,&k); init(); for(int i=1;i<=n;i++) { for(int j=1;j<=m+i-1;j++) { scanf("%d",&mat[i][j]); } } for(int i=1;i<=n;i++) { for(int j=1;j<=m+i-1;j++) { int p3=getnum(i,j); int p4=getnum2(i,j); add(p3,p4,-mat[i][j],1); add(p4,p3,mat[i][j],0); if(i<n) { int p1=getnum2(i,j); int p2=getnum(i+1,j); add(p1,p2,0,1); add(p2,p1,0,0); p2=getnum(i+1,j+1); add(p1,p2,0,1); add(p2,p1,0,0); } } } for(int i=1;i<=m;i++) { add(0,i,0,1); add(i,0,0,0); } for(int i=1;i<=m+n-1;i++) { add(getnum2(n,i),t,0,1); add(t,getnum2(n,i),0,0); } for(int i=1;i<=k;i++)//只用找k条路径,所以只用k次 { if(spfa()) add(); } printf("%d\n",-mincost); return 0; } /* 3 2 2 1 2 5 0 2 1 10 0 6 */
相关文章推荐
- 【wikioi】1033 蚯蚓的游戏问题(费用流)
- 【wikioi1033】蚯蚓的游戏问题
- 【wikioi1033】蚯蚓的游戏问题(9018p1277)
- 蚯蚓的游戏问题 wikioi 1033
- wikioi 蚯蚓的游戏问题 (费用流模板1)
- 【CODEVS】1033 蚯蚓的游戏问题
- codevs 1033 蚯蚓的游戏问题 费用流+拆点
- CODE[VS] 1033 蚯蚓的游戏问题(最大费用最大流?)
- 【codevs1033】 蚯蚓的游戏问题
- codevs 1033 蚯蚓的游戏问题----费用流
- 1033 蚯蚓的游戏问题
- CODEVS_1033 蚯蚓的游戏问题 网络流 最小费用流 拆点
- [codevs 1033] 蚯蚓的游戏问题
- 【codevs1033】蚯蚓的游戏问题
- [codevs 1033] 蚯蚓的游戏问题
- CODEVS 1033 蚯蚓的游戏问题
- codevs 1033 蚯蚓的游戏问题
- codevs1033 蚯蚓的游戏问题
- 【CODEVS1033】蚯蚓的游戏问题(费用流)
- CODEVS_1033 蚯蚓的游戏问题 网络流 最小费用流 拆点