HDU 3488 费用流 圈
来源:互联网 发布:达芬奇调色 知乎 编辑:程序博客网 时间:2024/05/16 12:10
题意:给你n个点,m条边,让你找出若干个环,使得每个点只属于一个环,且每个环至少两个点。
分析:本题其实KM算法就行,而且速度也快,但是网络流也可行。。。既然每个点只属于一个环,那么每个点的入度和初度都为一,我们把每个点拆成两个点,其中一个点连接S,另一个连接T,容量都为1,然后每条输入边再加入图中,跑一遍最小费用最大流即可,这样若最大流为n,则每个点的入度和初度就都为1了。
代码:
//O(Kn^2m)//如果要求最大费用的话 只需在加边的时候加-的边 输出时输出-ans即可#pragma comment(linker,"/STACK:102400000,102400000")#include <iostream>#include <string.h>#include <stdio.h>#include <algorithm>#include <vector>#include <string>#include <math.h>#include <queue>#include <stack>#include <map>#include <set>using namespace std;typedef long long ll; //记得必要的时候改成无符号const int maxn=505;const int maxm=1000005;const int INF=1000000000;struct EdgeNode{ int from; int to; int flow; int cost; int next;}edge[maxm];int head[maxn],cnt;void add(int x,int y,int z,int c){edge[cnt].from=x;edge[cnt].to=y;edge[cnt].flow=z;edge[cnt].cost=c;edge[cnt].next=head[x];head[x]=cnt++;edge[cnt].from=y;edge[cnt].to=x;edge[cnt].flow=0;edge[cnt].cost=-c;edge[cnt].next=head[y];head[y]=cnt++;}void init(){ cnt=0; memset(head,-1,sizeof(head));}int S,T,n,m;int d[maxn],in[maxn],pre[maxn];queue<int>Q;bool spfa(int S,int T){ int u,v,f,c; while(!Q.empty())Q.pop(); memset(in,0,sizeof(in)); for(int i=0;i<=n;i++)d[i]=INF; d[S]=0; Q.push(S); while(!Q.empty()) { u=Q.front(); Q.pop(); in[u]=0; for(int i=head[u];i!=-1;i=edge[i].next){ v=edge[i].to; f=edge[i].flow; c=edge[i].cost; if(f&&d[u]+c<d[v]){ d[v]=d[u]+c; pre[v]=i; if(!in[v]){ in[v]=1; Q.push(v); } } } } if(d[T]==INF)return false; return true;}int MCMF(int S,int T,int need=0){ int u; int max_flow=0; int min_cost=0; while(spfa(S,T)) { int flow=INF; u=T; while(u!=S){ flow=min(flow,edge[pre[u]].flow); u=edge[pre[u]].from; } u=T; max_flow+=flow; min_cost+=d[T]*flow; while(u!=S){ edge[pre[u]].flow-=flow; edge[pre[u]^1].flow+=flow; u=edge[pre[u]].from; } } if(max_flow<need) return -1; return min_cost;}int main(){ int cs,i,x,y,z; scanf("%d",&cs); while(cs--){ init(); scanf("%d%d",&n,&m); S=0; T=2*n+1; for(i=1;i<=n;i++){ add(S,i,1,0); add(i+n,T,1,0); } for(i=1;i<=m;i++){ scanf("%d%d%d",&x,&y,&z); //add(x,y,1,z); add(x,y+n,1,z); } n=T+1; printf("%d\n",MCMF(S,T)); } return 0;}
0 0
- HDU 3488 费用流 圈
- HDU 3488 最小费用圈覆盖
- hdu1853/ hdu 3488 有向图,取k个圈覆盖所有点一次//费用流
- HDU 1853 Cyclic Tour 费用流(圈)
- HDOJ1853-费用流(圈,拆点)
- poj 2175 费用流+消圈
- hdu 3488(费用流)
- HDU 3488 Tour 费用流
- HDU 3488 最小费用流
- HDU 3488 HDU 3435 HDU 1853 | 费用流
- HDU 3488 最小费用最大流模板
- hdu 3488 Tour(费用流,去重边)
- hdu 3488 Tour【最小费用最大流】
- Arrest HDU 费用流
- hdu 3667 费用流
- HDU 3376 费用流
- hdu 1853 费用流
- HDU 1533 费用流
- Wikioi 1012
- Permutations
- 初学thinkphp
- Wikioi 1014
- hud_bone Collector
- HDU 3488 费用流 圈
- 十大致癌食物黑名单公布 葵花子竟然排第一(图)
- 树链剖分-点的分治(链的点的个数为k的点对数)
- Android 网络通信框架Volley简介(Google IO 2013)
- POJ 1195 Mobile phones(树状数组)
- hdu 2089 不要62
- 多校联合训练赛 第三场--B - The battle near the swamp
- Ubuntu12.04 侧边栏不显示图标-解决方案
- HDU 3033 I love sneakers! (DP 01背包+完全背包)