您的位置:首页 > 其它

bzoj1221 [HNOI2001]软件开发 & bzoj3280 小R的烦恼

2016-07-17 11:23 363 查看
学学硕神偷懒,这两道题的确很像啊。。

一开始我是一脸懵逼的,幸好看懂了题解,这种构图很巧妙啊~

黄学长说,这是经典餐巾问题,我觉得他讲的很好。大家可以去看看.点击打开链接

按照这个说法建图就好啦。

关于第二题(bzoj3280),需要考虑的就多一点。

其实我觉得还要想通一个问题,在二分图的左边还是右边的i和i+1连边呢?

给个3280的代码

#include
#include
#include
#include
#include
#include
#include
#include
#define Max 0x7fffffff
#define me(a,x) memset(a,x,sizeof a)
#define cp(a,x) memcpy(a,x,sizeof a)
using namespace std;
struct node
{
int x,y,c,d,next;
}a[20100]; int len,first[2010];
void ins(int x,int y,int c,int d)
{
a[++len].x=x,a[len].y=y,a[len].c=c,a[len].d=d;
a[len].next=first[x],first[x]=len;
a[++len].x=y,a[len].y=x,a[len].c=0,a[len].d=-d;
a[len].next=first[y],first[y]=len;
}
int d[2010],t,l[2010];
bool v[2010];
queueq;
bool spfa()
{
for(int i=0;i<=t;i++)l[i]=v[i]=0,d[i]=Max;
v[0]=1,d[0]=0; q.push(0);
while(!q.empty())
{
int x=q.front();
for(int k=first[x];k;k=a[k].next)
{
int y=a[k].y;
if(d[y]>d[x]+a[k].d && a[k].c)
{
d[y]=d[x]+a[k].d;
l[y]=k;
if(!v[y]){v[y]=1; q.push(y);}
}
}
q.pop(); v[x]=0;
}
return d[t]!=Max;
}
int main()
{
int T;
scanf("%d",&T);
for(int ca=1;ca<=T;ca++)
{
int n,m,k,x,y,i,j,p=0;
scanf("%d%d%d",&n,&m,&k); t=n+n+1;
len=1; me(first,0);
for(i=1;i<=n;i++)
{
scanf("%d",&x); p+=x;
ins(0,i,x,0),ins(i+n,t,x,0);
if(i+1<=n)ins(i+n,i+n+1,Max,0);
}
for(i=1;i<=m;i++)
{
scanf("%d%d",&x,&y);
ins(0,n+1,x,y);
}
for(i=1;i<=k;i++)
{
scanf("%d%d",&x,&y);
for(j=1;j<=n-x-1;j++)
ins(j,j+x+1+n,Max,y);
}
int ans=0,u;
while(spfa())
{
u=Max;
for(i=l[t];i;i=l[a[i].x])
u=min(u,a[i].c);
p-=u;
for(i=l[t];i;i=l[a[i].x])
a[i].c-=u,a[i^1].c+=u,ans+=a[i].d*u;
}
printf("Case %d: ",ca);
if(p==0)printf("%d\n",ans);
else printf("impossible\n");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: