学学硕神偷懒,这两道题的确很像啊。。 一开始我是一脸懵逼的,幸好看懂了题解,这种构图很巧妙啊~ 黄学长说,这是经典餐巾问题,我觉得他讲的很好。大家可以去看看.点击打开链接 按照这个说法建图就好啦。 关于第二题(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]; queue q; 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; }