您的位置:首页
hdu 2987最大权闭合图模板类型题
2017-08-08 19:13
197 查看
/* 最大权闭合图模板类型的题,考验对知识概念的理解。 题意:如今要辞退一部分员工。辞退每个员工能够的到一部分利益(能够是负的),而且辞退员工,必须辞退他的下属。求最大利益和辞退的最小人数。 最大权闭合图模板类型。 求出最大权后沿着源点s,dfs到的点就为最小的人数。 证明/* 转载:利用一个经典的trick:多keyword > 建图前,对全部b[i],运行变换b[i]=b[i]*10000-1。然后。会惊异地发现, > 此时最大流所相应的方案就是满足辞退最少人数的了。 > 为什么?显然,变换后的流量r2除以10000后再取整就等于原来的流量,可是 > r2的后四位却蕴含了辞退人数的信息:每多辞退一个人,流量就会少1。 > > 剩下的就是怎样依据一个网络流输出方案。 > 我的做法:从源点開始沿着残余网络dfs(仅仅走没有满载的边), > 能dfs到的点相应的人就是须要辞退的。*/ */ #include"stdio.h" #include"string.h" #include"string" #include"queue" #define ll __int64 #define N 9999 #define inf 0x3fffffff using namespace std; struct node { ll u,v,w,next; }bian[N*50]; ll fee ; ll head ,yong,s,t,dis ; void init(){ yong=0; memset(head,-1,sizeof(head)); memset(dis,-1,sizeof(dis)); } void addedge(ll u,ll v,ll w) { bian[yong].u=u; bian[yong].v=v; bian[yong].w=w; bian[yong].next=head[u]; head[u]=yong++; } void add(ll u,ll v,ll w) { addedge(u,v,w); addedge(v,u,0); } void bfs() { ll u,v,i; queue<ll>q; q.push(t); dis[t]=0; while(!q.empty()) { u=q.front(); q.pop(); for(i=head[u];i!=-1;i=bian[i].next) { v=bian[i].v; if(dis[v]==-1) { dis[v]=dis[u]+1; q.push(v); } } } return ; } ll ISAP() { ll sum=0; bfs(); ll gap ,cur ,stac ,top,i; memset(gap,0,sizeof(gap)); for(i=s;i<=t;i++) { gap[dis[i]]++; cur[i]=head[i]; } ll k=s; top=0; while(dis[s]<t+1) { if(k==t) { ll minn=inf,index; for(i=0;i<top;i++) { ll e=stac[i]; if(minn>bian[e].w) { minn=bian[e].w; index=i; } } for(i=0;i<top;i++) { ll e=stac[i]; bian[e].w-=minn; bian[e^1].w+=minn; } sum+=minn; top=index; k=bian[stac[top]].u; } for(i=cur[k];i!=-1;i=bian[i].next) { ll v=bian[i].v; if(bian[i].w&&dis[k]==dis[v]+1) { cur[k]=i; k=v; stac[top++]=i; break; } } if(i==-1) { ll m=t+1; for(i=head[k];i!=-1;i=bian[i].next) if(m>dis[bian[i].v]&&bian[i].w) { m=dis[bian[i].v]; cur[k]=i; } if(--gap[dis[k]]==0)break; gap[dis[k]=m+1]++; if(k!=s) k=bian[stac[--top]].u; } } return sum; } ll cou=0,vis ; void dfs(ll u){//,ll pre) {会形成环越界 ll i,j; cou++; vis[u]=1; for(i=head[u];i!=-1;i=bian[i].next) { j=bian[i].v; if(bian[i].w&&!vis[j]) { dfs(j); } } return ; } int main() { ll n,m,i,j,sum; while(scanf("%I64d%I64d",&n,&m)!=EOF) { init(); s=0;t=n+1;sum=0; for(i=1;i<=n;i++) { scanf("%I64d",&fee[i]); if(fee[i]>0) { add(s,i,fee[i]); sum+=fee[i]; } else add(i,t,-fee[i]); } while(m--) { scanf("%I64d%I64d",&i,&j); add(i,j,inf); } cou=0; sum=sum-ISAP(); memset(vis,0,sizeof(vis)); dfs(0); printf("%I64d %I64d\n",cou-1,sum); } return 0; }
相关文章推荐
- hdu 2987最大权闭合图模板类型题
- hdu 2987最大权闭合图模板类型题
- 用模板比较不同类型值,求出最大的那个
- Battle (hdu 3061 最大权闭合图模板题)
- bzoj 1497: [NOI2006]最大获利-----------算法模板[最大权闭合子图]&省选计划系列
- 利用C++模板特性计算各整数类型的最大最小值
- (模板)最大权闭合图(POJ2987)
- 体验和理解函数模板-----求最大值(默认函数类型)
- 最大权闭合图 hdu 3879 Base Station 有模板!
- (模板)最大权闭合图
- poj 2987 最大权闭合图 最大流最小割模板
- 4-5 求自定类型元素的最大值
- 网络流模板 最大流maxflow
- poj2987 最大权闭合图问题
- 线段树模板(区间和+区间最大值 + LAZY标记)
- C++带模板结构体 类型重定义*
- float类型最大值和最小值
- 最大网络流 模板
- C/C++中各种类型int、long、double、char表示范围(最大最小值)(转)
- 最大权闭合图