BZOJ 2502: 清理雪道
题目大意:
求最少的链能覆盖一个DAG,可以重复。
题解:
比较显然的上下界最小流,其实没有上界。
代码:
#include<cstdio>
#include<algorithm>
using namespace std;
int cnt,n,S,T,SS,TT,d[1000005],q[1000005],cur[1000005],last[1000005],h[1000005];
struct node{
int to,next,cap;
}e[1000005];
void add(int a,int b,int c){
e[++cnt].to=b;
e[cnt].cap=c;
e[cnt].next=last[a];
last[a]=cnt;
}
void ADD(int a,int b,int c){
add(a,b,c);
add(b,a,0);
}
void build(int a,int b,int minn,int maxx){
ADD(a,b,maxx-minn);
d[a]-=minn;
d[b]+=minn;
}
int bfs(int S,int T){
for (int i=1; i<=n+4; i++) h[i]=-1;
h[S]=0;
int head=0,tail=1;
q[tail]=S;
while (head<tail){
int x=q[++head];
for (int i=last[x]; i; i=e[i].next){
int V=e[i].to;
if (e[i].cap && h[V]==-1){
h[V]=h[x]+1;
q[++tail]=V;
}
}
}
return h[T]!=-1;
}
int dfs(int x,int T,int low){
if (x==T) return low;
int used=0;
for (int i=cur[x]; i; i=e[i].next){
int V=e[i].to;
if (e[i].cap && h[V]==h[x]+1){
int w=dfs(V,T,min(e[i].cap,low-used));
e[i].cap-=w;
e[i^1].cap+=w;
cur[x]=i;
used+=w;
if (used==low) return low;
}
}
if (!used) h[x]=-1;
return used;
}
int dinic(int S,int T){
int ans=0;
while (bfs(S,T)){
for (int i=1; i<=n+4; i++) cur[i]=last[i];
ans+=dfs(S,T,1e9);
}
return ans;
}
int main(){
cnt=1;
scanf("%d",&n);
int S=n+1,T=n+2,SS=n+3,TT=n+4;
for (int x=1; x<=n; x++){
int len;
scanf("%d",&len);
for (int i=1; i<=len; i++){
int y;
scanf("%d",&y);
build(x,y,1,1e6);
}
}
for (int i=1; i<=n; i++){
build(S,i,0,1e6);
build(i,T,0,1e6);
}
for (int i=1; i<=T; i++){
if (d[i]>0) ADD(SS,i,d[i]);
else ADD(i,TT,-d[i]);
}
ADD(T,S,1e6);
dinic(SS,TT);
int ans=e[cnt].cap;
e[cnt].cap=e[cnt-1].cap=0;
printf("%d\n",ans-dinic(T,S));
return 0;
}

浙公网安备 33010602011771号