BZOJ1449: [JSOI2009]球队收益
Description
Input
Output
一个整数表示联盟里所有球队收益之和的最小值。
Sample Input
3 3
1 0 2 1
1 1 10 1
0 1 3 3
1 2
2 3
3 1
1 0 2 1
1 1 10 1
0 1 3 3
1 2
2 3
3 1
Sample Output
43
HINT
这题挺逗的。。。很好看出来是网络流难点就在于你不能在跑网络流的时候把输赢的利益一起算上所以做法很光(you)棍(xiu):每场比赛每队都算输,然后看看是哪个赢根据它给的公式可以拆开,对于每一个球队,就建出每多赢一场的利益它说明了它Ci>=Di,所以这肯定是递增的,就可以直接跑最小费用最大流了
代码如下:
//MT_LI #include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> #include<queue> #include<vector> #include<ctime> #include<map> #include<bitset> #include<set> #define ll long long #define mp(x,y) make_pair(x,y) #define pll pair<long long,long long> #define pii pair<int,int> using namespace std; inline int read() { int f=1,x=0;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } int stack[20]; inline void write(int x) { if(x<0){putchar('-');x=-x;} if(!x){putchar('0');return;} int top=0; while(x)stack[++top]=x%10,x/=10; while(top)putchar(stack[top--]+'0'); } inline void pr1(int x){write(x);putchar(' ');} inline void pr2(int x){write(x);putchar('\n');} struct node{ int x,y,c,d,next,other; }a[21000];int len,last[11000]; void ins(int x,int y,int c,int d) { a[++len]=(node){x,y,c,d,last[x],len+1};last[x]=len; a[++len]=(node){y,x,0,-d,last[y],len-1};last[y]=len; } int lose[5100],win[5100],c[5100],d[5100]; int n,m,st,ed; int head,tail,list[110000]; int D[11000],ans; int cc[11000],pre[11000]; bool v[11000]; bool spfa() { for(int i=1;i<=ed;i++)D[i]=9999999; D[st]=0; memset(v,false,sizeof(v));v[st]=true; memset(cc,0,sizeof(cc));cc[st]=99999999; list[1]=st;head=1;tail=2; while(head!=tail) { int x=list[head]; for(int k=last[x];k;k=a[k].next) { int y=a[k].y; if(a[k].c>0&&D[y]>D[x]+a[k].d) { D[y]=D[x]+a[k].d; pre[y]=k; cc[y]=min(cc[x],a[k].c); if(v[y]==false) { v[y]=true; list[tail++]=y; } } } head++; v[x]=false; } if(D[ed]==9999999)return false; ans+=D[ed]*cc[ed]; int x=ed; while(x!=0) { int k=pre[x]; a[k].c-=cc[ed];a[a[k].other].c+=cc[ed]; x=a[k].x; } return true; } int match[5100]; int main() { n=read();m=read(); len=0;memset(last,0,sizeof(last)); for(int i=1;i<=n;i++)win[i]=read(),lose[i]=read(),c[i]=read(),d[i]=read(); st=0;ed=n+m+1; for(int i=1;i<=m;i++) { ins(st,i,1,0); int x=read(),y=read(); ins(i,x+m,1,0);ins(i,y+m,1,0); match[x]++,match[y]++; } for(int i=1;i<=n;i++)lose[i]+=match[i]; int sum=0; for(int i=1;i<=n;i++) sum+=win[i]*win[i]*c[i]+lose[i]*lose[i]*d[i]; for(int i=1;i<=n;i++) for(int j=1;j<=match[i];j++) { ins(i+m,ed,1,2*c[i]*win[i]+c[i]+d[i]-2*d[i]*lose[i]); win[i]++,lose[i]--; } ans=0; while(spfa()); printf("%d\n",sum+ans); return 0; }
The deepest love I think,later than apart,I will live as you like