1449: [JSOI2009]球队收益

1449: [JSOI2009]球队收益

Time Limit: 5 Sec  Memory Limit: 64 MB
Submit: 757  Solved: 437
[Submit][Status][Discuss]

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

Sample Output

43

HINT

Source

#include<cstdio>
#include<cstring>
#include<iostream>
#define b(x) (x*x)
#define IN inline
using namespace std;
IN int read(){
    register int x=0,f=1;
    register 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;
}
const int N=1e5+10;
const int M=6010;
const int inf=1e9;
struct node{
    int v,next,cap,cost;
}e[N*10];int tot=1;
int n,m,S,T,ans,head[M],dis[M],q[N*10];
int win[M],lose[M],C[M],D[M],rem[M];
bool vis[M];
IN void add(int x,int y,int cap,int cost){
    e[++tot].v=y;e[tot].cap=cap;e[tot].cost=cost;e[tot].next=head[x];head[x]=tot;
    e[++tot].v=x;e[tot].cap=0;e[tot].cost=-cost;e[tot].next=head[y];head[y]=tot;
}
IN bool spfa(){
    for(int i=S;i<=T;i++) vis[i]=0,dis[i]=inf;
    int h=0,t=1;q[t]=T;dis[T]=0;vis[T]=1;
    while(h!=t){
        int x=q[++h];vis[x]=0;
        for(int i=head[x];i;i=e[i].next){
            int v=e[i].v;
            if(e[i^1].cap&&dis[v]>dis[x]+e[i^1].cost){
                dis[v]=dis[x]+e[i^1].cost;
                if(!vis[v]){
                    vis[v]=1;
                    q[++t]=v;
                }
            }
        }
    }
    return dis[S]<inf;
}
int dfs(int x,int f){
    vis[x]=1;
    if(x==T) return f;
    int used=0,w;
    for(int i=head[x];i;i=e[i].next){
        int v=e[i].v;
        if(!vis[v]&&e[i].cap&&dis[v]+e[i].cost==dis[x]){
            w=dfs(v,min(f-used,e[i].cap));
            e[i].cap-=w;e[i^1].cap+=w;
            ans+=w*e[i].cost;
            used+=w;
            if(used==f) return used;
        }
    }
    return used;
}
IN void zkw(){
    while(spfa()){
        vis[T]=1;
        while(vis[T]){
            memset(vis,0,sizeof vis);
            dfs(S,inf);
        }
    }
}
int main(){
    n=read();m=read();S=0;T=n+m+1;
    for(int i=1;i<=n;i++) win[i]=read(),lose[i]=read(),C[i]=read(),D[i]=read();
    for(int i=1,x,y;i<=m;i++){
        x=read();y=read();rem[x]++;rem[y]++;
        add(S,i,1,0);
        add(i,x+m,1,0);
        add(i,y+m,1,0);
    }
    for(int i=1;i<=n;i++) lose[i]+=rem[i];
    for(int i=1;i<=n;i++) ans+=b(win[i])*C[i]+b(lose[i])*D[i];
    for(int i=1;i<=n;i++){
        for(int j=1;j<=rem[i];j++){
            add(i+m,T,1,2*win[i]*C[i]-2*lose[i]*D[i]+C[i]+D[i]);
            win[i]++;lose[i]--;
        }
    }
    zkw();
    printf("%d",ans);
    return 0;
}
原文地址:https://www.cnblogs.com/shenben/p/6261445.html