省选模拟赛 project
solution:
最小割问题。
建如下边:
(S,i,Ai)代表选用A语言编写第i个项目;
(i,T,Bi)代表选用A语言编写第i个项目;
其后注意要反向连边
(i,j,D)代表选用B语言编写第i个项目,选用A语言编写第j个项目;
(j,i,C)代表选用A语言编写第i个项目,选用B语言编写第j个项目;
litc学长出的题,引文最小割题目做的少,想的少,考试时一直没写出来,按题解自己写了个ISAP,已通过所有测试点。
#include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> using namespace std; typedef long long ll; int n,m,S,T,A,B,ecnt,first[600000]; struct Edge{int u,v,nxt,cap,flow;}e[1050000]; bool vis[600000]; int q[600000],d[600000],p[600000],num[600000],cur[600000]; void Link(int u,int v,ll w) { e[++ecnt].u=u,e[ecnt].v=v,e[ecnt].cap=w,e[ecnt].flow=0; e[ecnt].nxt=first[u],first[u]=ecnt; e[++ecnt].u=v,e[ecnt].v=u,e[ecnt].cap=0,e[ecnt].flow=0; e[ecnt].nxt=first[v],first[v]=ecnt; } void bfs() { int head=0,tail=1; memset(vis,false,sizeof(vis)); q[0]=T,d[T]=0,vis[T]=true; while(head^tail){ int now=q[head++]; for(int i=first[now];i;i=e[i].nxt) if(!vis[e[i].u]&&e[i].cap>e[i].flow){ vis[e[i].u]=true; d[e[i].u]=d[now]+1; q[tail++]=e[i].u; } } } int Agument() { int x=T,a=0x7fffffff; while(x^S){ a=min(a,e[p[x]].cap-e[p[x]].flow); x=e[p[x]].u; } x=T; while(x^S){ e[p[x]].flow+=(ll)a; e[p[x]^1].flow-=(ll)a; x=e[p[x]].u; } return a; } ll ISAP() { int x=S; ll flow=0; bfs(); memset(num,0,sizeof(num)); for(int i=S;i<=T;i++) num[d[i]]++,cur[i]=first[i]; while(d[S]<n+1){ if(!(x^T)){ flow+=(ll)Agument(); x=S; } bool advanced=false; for(int i=cur[x];i;i=e[i].nxt) if(e[i].cap>e[i].flow&&d[x]==d[e[i].v]+1){ advanced=true; cur[x]=p[e[i].v]=i; x=e[i].v; break; } if(!advanced){ int mn=n; for(int i=first[x];i;i=e[i].nxt) if(e[i].cap>e[i].flow) mn=min(mn,d[e[i].v]); if(--num[d[x]]==0)break; num[d[x]=mn+1]++; cur[x]=first[x]; if(x^S)x=e[p[x]].u; } } return flow; } int main() { freopen("project.in","r",stdin); freopen("project.out","w",stdout); scanf("%d%d",&n,&m); S=0,T=n+1,ecnt=1; for(int i=1;i<=n;i++){ int x,y; scanf("%d%d",&x,&y); Link(S,i,x); Link(i,T,y); } for(int i=1;i<=m;i++){ int x,y,c,d; scanf("%d%d%d%d",&x,&y,&c,&d); Link(x,y,d); Link(y,x,c); } printf("%I64d\n",ISAP());//output 'min cut'; fclose(stdin);fclose(stdout); return 0; }