首页 > 代码库 > POJ 2135 最小费用最大流
POJ 2135 最小费用最大流
思路:刚开始看的时候还不知道这题用最小费用最大流来做,因为里面没有流量啊,只有费用。而题目要求从1到n,再从n到1的时候两条路径不能同享一条路径,所以流量就从这来了。
因为两条路不同,所以设两点之间流量为1,建立超级源点和超级汇点的流量都为2就可以保证两条路径不同了,以前做最大流的时候还不知道原来流量有这功能,惭愧啊……
然后用最小费用最大流算法搞一下就A了。先用spfa求出最小费用的路径,这条路径就是以前做最大流的时候相当增广路了,然后这条最小费用路径再用EK算法求最小流量,就是最小费用最大流了,原来也挺容易的。图论最难的还是建图,这点深怕不疑啊!!,,。、
#pragma comment(linker, "/STACK:1024000000,1024000000") #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<map> #include<queue> #include<set> #include<cmath> #include<bitset> #define mem(a,b) memset(a,b,sizeof(a)) #define lson i<<1,l,mid #define rson i<<1|1,mid+1,r #define llson j<<1,l,mid #define rrson j<<1|1,mid+1,r #define INF 0x7fffffff typedef long long ll; typedef unsigned long long ull; using namespace std; #define maxn 50005 struct { int v,w,c,next,re; //re记录逆边的下标,c是费用,w是流量 } e[maxn]; int n,m,cnt; int head[maxn],que[maxn],pre[maxn],dis[maxn]; bool vis[maxn]; void add(int u, int v, int w, int c) { e[cnt].v=v,e[cnt].w=w,e[cnt].c=c; e[cnt].next=head[u]; e[cnt].re=cnt+1,head[u]=cnt++; e[cnt].v=u,e[cnt].w=0,e[cnt].c=-c; e[cnt].next=head[v]; e[cnt].re=cnt-1,head[v]=cnt++; } bool spfa() { int i, l = 0, r = 1; for(i = 0; i <= n; i ++) dis[i] = INF,vis[i] = false; dis[0]=0,que[0]=0,vis[0]=true; while(l<r) { int u=que[l++]; for(i=head[u];i!=-1;i=e[i].next) { int v = e[i].v; if(e[i].w&&dis[v]>dis[u]+e[i].c) { dis[v] = dis[u] + e[i].c; pre[v] = i; if(!vis[v]) { vis[v] = true; que[r ++] = v; } } } vis[u] = false; } return dis[n]!=INF; } int change() { int i,p,sum=INF,ans=0; for(i=n;i!=0;i=e[e[p].re].v) {//e[e[p].re].v为前向结点,不理解看add和spfa p=pre[i];//p为前向结点编号 sum=min(sum,e[p].w); } for(i=n;i!=0;i=e[e[p].re].v) { p=pre[i]; e[p].w-=sum; e[e[p].re].w+=sum; ans+=sum*e[p].c;//c记录的为单位流量费用,必须得乘以流量。 } return ans; } int EK() { int sum=0; while(spfa()) sum+=change(); return sum; } int main() { //freopen("1.txt","r",stdin); scanf("%d%d",&n,&m); int u,v,c; mem(head,-1);cnt=0; while(m--) { scanf("%d%d%d",&u,&v,&c); add(u,v,1,c),add(v,u,1,c); } add(0,1,2,0);//建超级源点 add(n,n+1,2,0);//建超级汇点 n++; printf("%d\n",dinic()); return 0; }
POJ 2135 最小费用最大流
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。