hdu 3987 Harry Potter and the Forbidden Forest 求割边最少的最小割
2012-09-01 13:03
337 查看
题意:
求最小割,但因为最小割是不唯一的,题目要求得到最小割的条件下,使得割边最少,输出最少割边数
思路:
有两种做法,但本质是一样的
第一种:
建边的时候每条边权 w = w * (E + 1) + 1;
这样得到最大流 maxflow / (E + 1) ,最少割边数 maxflow % (E + 1)
道理很简单,如果原先两类割边都是最小割,那么求出的最大流相等
但边权变换后只有边数小的才是最小割了
乘(E+1)是为了保证边数叠加后依然是余数,不至于影响求最小割的结果
第二种:
建图,得到最大流后,图中边若满流,说明该边是最小割上的边
再建图,原则:满流的边改为容量为 1 的边,未满流的边改为容量 INF 的边,然后最大流即答案
由于题目需要乘上最大的边数 而题目的最大边数有100000 所以数会很大 需要用64.在错了无限多次后终于搞对了。记得是他的花费要超int
还有就是记得用c++编译不用g++不然inf会超long int
先给出方法1的:耗时间78ms
求最小割,但因为最小割是不唯一的,题目要求得到最小割的条件下,使得割边最少,输出最少割边数
思路:
有两种做法,但本质是一样的
第一种:
建边的时候每条边权 w = w * (E + 1) + 1;
这样得到最大流 maxflow / (E + 1) ,最少割边数 maxflow % (E + 1)
道理很简单,如果原先两类割边都是最小割,那么求出的最大流相等
但边权变换后只有边数小的才是最小割了
乘(E+1)是为了保证边数叠加后依然是余数,不至于影响求最小割的结果
第二种:
建图,得到最大流后,图中边若满流,说明该边是最小割上的边
再建图,原则:满流的边改为容量为 1 的边,未满流的边改为容量 INF 的边,然后最大流即答案
由于题目需要乘上最大的边数 而题目的最大边数有100000 所以数会很大 需要用64.在错了无限多次后终于搞对了。记得是他的花费要超int
还有就是记得用c++编译不用g++不然inf会超long int
先给出方法1的:耗时间78ms
#include<iostream> #include<cstdio> #include<memory.h> #include<cmath> using namespace std; #define MAXN 5010 #define MAXE 1000100 #define INF 100000000000000000 int ne,nv,tmp,s,t,index; struct Edge{ int next,pair,v; __int64 cap,fLow; }edge[MAXE]; int net[MAXN]; __int64 ISAP() { int numb[MAXN],dist[MAXN],curedge[MAXN],pre[MAXN]; __int64 cur_fLow,max_fLow; int u,tmp,neck,i; memset(dist,0,sizeof(dist)); memset(numb,0,sizeof(numb)); memset(pre,-1,sizeof(pre)); for(i = 1 ; i <= nv ; ++i) curedge[i] = net[i]; numb[nv] = nv; max_fLow = 0; u = s; while(dist[s] < nv) { if(u == t) { cur_fLow = INF+1; for(i = s; i != t;i = edge[curedge[i]].v) { if(cur_fLow > edge[curedge[i]].cap) { neck = i; cur_fLow = edge[curedge[i]].cap; } } for(i = s; i != t; i = edge[curedge[i]].v) { tmp = curedge[i]; edge[tmp].cap -= cur_fLow; edge[tmp].fLow += cur_fLow; tmp = edge[tmp].pair; edge[tmp].cap += cur_fLow; edge[tmp].fLow -= cur_fLow; } max_fLow += cur_fLow; u = neck; } for(i = curedge[u]; i != -1; i = edge[i].next) if(edge[i].cap > 0 && dist[u] == dist[edge[i].v]+1) break; if(i != -1) { curedge[u] = i; pre[edge[i].v] = u; u = edge[i].v; }else{ if(0 == --numb[dist[u]]) break; curedge[u] = net[u]; for(tmp = nv,i = net[u]; i != -1; i = edge[i].next) if(edge[i].cap > 0) tmp = tmp<dist[edge[i].v]?tmp:dist[edge[i].v]; dist[u] = tmp + 1; ++numb[dist[u]]; if(u != s) u = pre[u]; } } return max_fLow; } void addedge(int u,int v,__int64 f) { edge[index].next = net[u]; edge[index].v = v; edge[index].cap = f; edge[index].fLow = 0; edge[index].pair = index+1; net[u] = index++; edge[index].next = net[v]; edge[index].v = u; edge[index].cap = 0; edge[index].fLow = 0; edge[index].pair = index-1; net[v] = index++; } int main() { int i,j,np,nc,m,n; int a,b,d,k,vaL; int te; int cases=1; scanf("%d",&te); while(te--) { scanf("%d%d",&n,&m); nv=n; index=1; if(n==0 && m==0) return 0; s = 1; t = n; memset(net,-1,sizeof(net)); for(i=1;i<=m;i++) { int u,v,d; __int64 c; scanf("%d%d%I64d%d",&u,&v,&c,&d); u++,v++; addedge(u,v,c*100001+1); if(d) addedge(v,u,c*100001+1); } __int64 ans=ISAP(); printf("Case %d: %I64d\n", cases++, ans % 100001); } return 0; }
相关文章推荐
- hdu 3987 求割边最少的最小割
- HDU 3987 Harry Potter and the Forbidden Forest (求割边最少的最小割)
- hdu 3987 Harry Potter and the Forbidden Forest 求将s和t隔开的最少费用下的最小边数 最小割
- HDU 3987 Harry Potter and the Forbidden Forest(最小割中的最少割边)经典
- HDU 3987 Harry Potter and the Forbidden Forest(最小割的最少割边数)
- hdu 3987 求割边最少的最小割
- hdu 3987(求边最少的最小割)
- hdu 3987 Harry Potter and the Forbidden Forest 求割边最少的最小割
- hdu 3987 求割边最少的最小割
- hdu 3987(求割边最小的最小割)
- hdu 3987(最小割的边数)
- HDU 6214 Smallest Minimum Cut(求最小割的最少边数)
- 【HDU】3987 Harry Potter and the Forbidden Forest 最小割
- HDU 4289 最小割=最大流 求去掉最少点权值使得 起末点不连通
- hdu 3987 Harry Potter and the Forbidden Forest 最小割
- hdu Smallest Minimum Cut 边数最少的最小割
- HDU 3987 最小割模型
- HDU 3987 Harry Potter and the Forbidden Forest最小割
- hdu 3987 Harry Potter and the Forbidden Forest【网路流最小割模型】
- hdu 3987 Harry Potter and the Forbidden Forest (最小割)