真是道挺不错的题,构图很棒。 而且还是个双倍经验题23333,由截图可见,权限狗的题数据更好、
我觉得HZWER大神和硕神都讲得很好了,我也就继续偷懒了硕神的 hzwer's
分析可以参考硕神的,关于构图,我们要想清楚怎么拆边,细节不太多,挺好的题。
贴代码
#include
#include
#include
#include
#include
#include
#define Max 0x7fffffff #define me(a,x) memset(a,x,sizeof a) using namespace std; struct node { int x,y,c,d,next; }a[50100]; int len,first[6010]; 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[6010],t,l[6010]; bool v[6010]; 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 win[5010],lose[5010],c1[5010],c2[5010]; int in[5010]; int main() { int n,m,i,j,x,y; scanf("%d%d",&n,&m); t=n+m+1; for(i=1;i<=n;i++)scanf("%d%d%d%d",&win[i],&lose[i],&c1[i],&c2[i]); int ans=0; me(in,0); len=1; me(first,0); for(i=1;i<=m;i++) { scanf("%d%d",&x,&y); in[x]++,in[y]++,lose[x]++,lose[y]++; ins(i,x+m,1,0),ins(i,y+m,1,0); ins(0,i,1,0); } for(i=1;i<=n;i++) ans+=c1[i]*win[i]*win[i]+c2[i]*lose[i]*lose[i]; for(i=1;i<=n;i++) for(j=1;j<=in[i];j++) { ins(i+m,t,1,c1[i]*(2*win[i]+1)+c2[i]*(-2*lose[i]+1)); win[i]++,lose[i]--; } while(spfa()) { for(i=l[t];i;i=l[a[i].x]) a[i].c--,a[i^1].c++; ans+=d[t]; } printf("%d\n",ans); return 0; }