HDU

题意:M台机器要生产n个糖果,糖果i的生产区间在(si, ti),花费是k(pi-si),pi是实际开始生产的时间机器,j从初始化到生产糖果i所需的时间Cij,花费是Dij,任意机器从生产糖果i到生产糖果j,需花费时间Eij,花费Fij求生产完所有糖果所需的最小时间?
题解:先把糖果拆点,s向i糖果连流量为1,费用为0,i+n糖果向t连流量为1,费用为0,n
2+i机器向t连流量为1,费用为0的边,如果i能流向j,那么j连i+n一条边流量为1,费用为(ti-sj)k+dij,如果机器j能流向i+2n,那么连一条边流量为1,费用为(p-s)*k+d,假设i流向了j,那么说明j在i之后生产,而且保证了每台机器只生产一种糖果

//#pragma GCC optimize(2)
//#pragma GCC optimize(3)
//#pragma GCC optimize(4)
//#pragma GCC optimize("unroll-loops")
//#pragma comment(linker, "/stack:200000000")
//#pragma GCC optimize("Ofast,no-stack-protector")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#include<bits/stdc++.h>
#define fi first
#define se second
#define db double
#define mp make_pair
#define pb push_back
#define pi acos(-1.0)
#define ll long long
#define vi vector<int>
#define mod 1000000007
#define ld long double
#define C 0.5772156649
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1
#define pll pair<ll,ll>
#define pil pair<int,ll>
#define pli pair<ll,int>
#define pii pair<int,int>
//#define cd complex<double>
#define ull unsigned long long
#define base 1000000000000000000
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
#define fin freopen("a.txt","r",stdin)
#define fout freopen("a.txt","w",stdout)
#define fio ios::sync_with_stdio(false);cin.tie(0)
template<typename T>
inline T const& MAX(T const &a,T const &b){return a>b?a:b;}
template<typename T>
inline T const& MIN(T const &a,T const &b){return a<b?a:b;}
inline void add(ll &a,ll b){a+=b;if(a>=mod)a-=mod;}
inline void sub(ll &a,ll b){a-=b;if(a<0)a+=mod;}
inline ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
inline ll qp(ll a,ll b){ll ans=1;while(b){if(b&1)ans=ans*a%mod;a=a*a%mod,b>>=1;}return ans;}
inline ll qp(ll a,ll b,ll c){ll ans=1;while(b){if(b&1)ans=ans*a%c;a=a*a%c,b>>=1;}return ans;}

using namespace std;

const double eps=1e-8;
const ll INF=0x3f3f3f3f3f3f3f3f;
const int N=300+10,maxn=400000+10,inf=0x3f3f3f3f;

struct edge{
    int to,Next,c;
    int cost;
}e[maxn];
int cnt,head[N];
int s,t;
int dis[N],pre[N],path[N];
bool vis[N];
void add(int u,int v,int c,int cost)
{
    e[cnt].to=v;
    e[cnt].c=c;
    e[cnt].cost=cost;
    e[cnt].Next=head[u];
    head[u]=cnt++;
    e[cnt].to=u;
    e[cnt].c=0;
    e[cnt].cost=-cost;
    e[cnt].Next=head[v];
    head[v]=cnt++;
}
bool spfa()
{
    memset(pre,-1,sizeof pre);
    memset(dis,inf,sizeof dis);
    memset(vis,0,sizeof vis);
    dis[s]=0;
    vis[s]=1;
    queue<int>q;
    q.push(s);
    while(!q.empty())
    {
        int x=q.front();
        q.pop();
        vis[x]=0;
        for(int i=head[x];~i;i=e[i].Next)
        {
            int te=e[i].to;
            if(e[i].c>0&&dis[x]+e[i].cost<dis[te])
            {
                dis[te]=dis[x]+e[i].cost;
                pre[te]=x;
                path[te]=i;
                if(!vis[te])q.push(te),vis[te]=1;
            }
        }
    }
    return pre[t]!=-1;
}
int n,m,k;
int mincostmaxflow()
{
    int cost=0,flow=0;
    while(spfa())
    {
        int f=inf;
        for(int i=t;i!=s;i=pre[i])
            if(e[path[i]].c<f)
               f=e[path[i]].c;
        flow+=f;
        cost+=dis[t]*f;
        for(int i=t;i!=s;i=pre[i])
        {
            e[path[i]].c-=f;
            e[path[i]^1].c+=f;
        }
    }
    if(flow!=n)return -1;
    return cost;
}
void init()
{
    memset(head,-1,sizeof head);
    cnt=0;
}
int cans[N],cant[N],ti[N][N];
int main()
{
    while(~scanf("%d%d%d",&n,&m,&k))
    {
        if(!n&&!m&&!k)break;
        init();
        s=2*n+m+1,t=2*n+m+2;
        for(int i=1;i<=m;i++)add(2*n+i,t,1,0);
        for(int i=1;i<=n;i++)
        {
            scanf("%d%d",&cans[i],&cant[i]);
            add(s,i,1,0);add(i+n,t,1,0);
        }
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                scanf("%d",&ti[i][j]);
        for(int i=1;i<=n;i++)
        {
            for(int j=1,x;j<=m;j++)
            {
                scanf("%d",&x);
                if(ti[i][j]<cant[i])
                {
                    add(i,2*n+j,1,max(0,ti[i][j] - cans[i])*k+x);
                }
            }
        }
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                scanf("%d",&ti[i][j]);
        for(int i=1;i<=n;i++)
        {
            for(int j=1,x;j<=n;j++)
            {
                scanf("%d",&x);
                if(cant[i] + ti[i][j] < cant[j] && i != j)add(j,n+i,1,max(0,cant[i] + ti[i][j] - cans[j])*k+x);
            }
        }
        printf("%d
",mincostmaxflow());
    }
    return 0;
}
/********************
3 2 1
4 7
2 4
8 9
4 4
3 3
3 3
2 8
12 3
14 6
-1 1 1
1 -1 1
1 1 -1
-1 5 5
5 -1 5
5 5 -1
********************/
原文地址:https://www.cnblogs.com/acjiumeng/p/9719392.html