您的位置:首页 > 其它

【bzoj1391】order

2016-01-01 17:37 316 查看
这个题还是很机智的。。

最大权闭合子图是怎样通过最小割来限制的 再此基础上稍微变一变。。

但是直接交上去会T 需要用当前弧优化

当前弧优化就是在dfs的时候将流量已经不能再增加的边标记出来 下次dfs的时候直接跳过这些边

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<queue>
#include<cmath>
using namespace std;
const int N=2511;
const int M=N*2000;
const int inf=0x3f3f3f3f;
int head
,next[M],key[M],w[M],tot;
int dist
,inq
;queue<int>q;
int S,T;
int cur
;//当前弧

void bili()
{
tot=-1;
memset(head,-1,sizeof(head));
}
void add(int x,int y,int z)
{
tot++;next[tot]=head[x];head[x]=tot;key[tot]=y;w[tot]=z;
tot++;next[tot]=head[y];head[y]=tot;key[tot]=x;w[tot]=0;
}
int bfs()
{
memset(dist,-1,sizeof(dist));
dist[S]=0;
q.push(S);
while(!q.empty())
{
int x=q.front();
q.pop();
inq[x]=0;
for(int i=head[x];i!=-1;i=next[i])
{
int y=key[i];
if(w[i]&&dist[y]==-1)
{
dist[y]=dist[x]+1;
if(inq[y]==0)q.push(y),inq[y]=1;
}
}
}
if(dist[T]==-1)return 0;
else return 1;
}
int zeng(int x,int b)
{
if(x==T)return b;
int now=0;
for(int i=cur[x];i!=-1&&now<b;i=next[i])
{
int y=key[i];
if(dist[y]==dist[x]+1&&w[i])
{
int temp=zeng(y,min(b-now,w[i]));
now+=temp;
w[i]-=temp;
w[i^1]+=temp;
if(w[i]>0)cur[x]=i;
}

}
if(now==0)dist[x]=-1;
return now;
}
int main()
{
//  cout<<64*1024*1024/4;
bili();
int n,m;
cin>>n>>m;
S=0,T=n+m+1;
int sum=0;
for(int i=1;i<=n;i++)
{
int wi,si;
scanf("%d%d",&wi,&si);
add(S,i,wi);sum+=wi;
for(int j=1;j<=si;j++)
{
int x,y;
scanf("%d%d",&x,&y);
add(i,n+x,y);
}
}
for(int i=1;i<=m;i++)
{
int x;
scanf("%d",&x);
add(i+n,T,x);
}
int ans=0;
while(bfs())
{
for(int i=S;i<=T;i++)cur[i]=head[i];
ans+=zeng(S,inf);
}

printf("%d",sum-ans);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: