HDU 6126 Give out candies(最小割-Dinic)

来源:互联网 发布:oracle12c新建数据库 编辑:程序博客网 时间:2024/06/16 13:03

Description

n个人,给每个人分1~m个糖果,有k个限制,每个限制给出x,y,z,表示第x个人分到的糖数减去第y个人分到的糖数不大于z,给第i个人j颗糖获得的满意度为wi,j,问总满意度最大值

Input

第一行一整数T表示用例组数,每组用例首先输入三个整数n,m,k表示人数,糖数和限制数,之后一个nm的矩阵wi,j为满意度矩阵,最后k行每行输入三个整数x,y,z表示一组限制(1T5,1n,m50,1k150,1x,yn,|z|<233)

Output

如果存在满足所有限制条件的方案,则输出满意度最大值,否则输出-1

Sample Input

2
2 1 1
1
1
1 2 1
3 3 2
1 2 3
2 3 1
3 1 2
1 2 0
2 3 0

Sample Output

2
7

Solution

把一个人i拆成m个点i1,i2,...,imij表示至少给第i个人j颗糖,该点属于源点集合表示条件成立,ijij+1连容量为1000wi,j的边(1j<m)im向汇点连容量为1000wi,m的边,对于限制x y znumxnumyzxiyiz连容量为无穷的边,那么最大满意度即为1000n最小割

Code

#include<cstdio>#include<iostream>#include<cstring>#include<algorithm>#include<cmath>#include<vector>#include<queue>#include<map>#include<set>#include<ctime>using namespace std;typedef long long ll;#define maxn 2505 #define maxm 20005#define INF 0x3f3f3f3fint head[maxn],cur[maxn],d[maxn],st[maxm],s,e,no;//s为源点,e为汇点,n为点数,no为边数 struct point{    int u,v,flow,next;    point(){};    point(int x,int y,int z,int w):u(x),v(y),next(z),flow(w){};}p[maxm];void add(int x,int y,int z)//从x到y建容量为z的边 {    p[no]=point(x,y,head[x],z);//前向弧,标号为偶     head[x]=no++;    p[no]=point(y,x,head[y],0);//后向弧,标号为奇     head[y]=no++;}void init()//初始化 {    memset(head,-1,sizeof(head));    no=0;}bool bfs(){    int i,x,y;    queue<int>q;    memset(d,-1,sizeof(d));    d[s]=0;     q.push(s);    while(!q.empty())    {        x=q.front();            q.pop();        for(i=head[x];i!=-1;i=p[i].next)        {            if(p[i].flow&& d[y=p[i].v]<0)            {                d[y]=d[x]+1;                if(y==e)                        return true;                q.push(y);            }        }    }    return false;}int dinic()//最大流 {    int i,loc,top,x=s,nowflow,maxflow=0;    while(bfs())    {        memcpy(cur,head,sizeof(head));        top=0;        while(true)        {            if(x==e)            {                nowflow=INF;                for(i=0;i<top;i++)                {                    if(nowflow>p[st[i]].flow)                    {                        nowflow=p[st[i]].flow;                        loc=i;                    }                }                for(i=0;i<top;i++)                {                    p[st[i]].flow-=nowflow;                    p[st[i]^1].flow+=nowflow;                }                maxflow+=nowflow;                top=loc;                    x=p[st[top]].u;            }            for(i=cur[x];i!=-1;i=p[i].next)                if(p[i].flow&&d[p[i].v]==d[x]+1)                     break;            cur[x]=i;            if(i!=-1)            {                st[top++]=i;                x=p[i].v;            }            else             {                if(!top)                        break;                d[x]=-1;                x=p[st[--top]].u;            }        }    }    return maxflow;}int T,n,m,k,w[55][55];int id(int i,int j){    return (i-1)*m+j;}int main(){    scanf("%d",&T);    while(T--)    {        scanf("%d%d%d",&n,&m,&k);        init();        s=0,e=n*m+1;        for(int i=1;i<=n;i++)            for(int j=1;j<=m;j++)                scanf("%d",&w[i][j]);        for(int i=1;i<=n;i++)        {            add(s,id(i,1),INF);            for(int j=1;j<m;j++)                add(id(i,j),id(i,j+1),1000-w[i][j]);            add(id(i,m),e,1000-w[i][m]);        }        while(k--)        {            int x,y,z;            scanf("%d%d%d",&x,&y,&z);            for(int i=1;i<=m;i++)                if(i-z>=1&&i-z<=m)                    add(id(x,i),id(y,i-z),INF);            if(m+1+z>=1&&m+1+z<=m)add(id(x,m+1+z),e,INF);        }        int ans=dinic();        if(ans>=INF)printf("-1\n");        else printf("%d\n",1000*n-ans);    }    return 0;}
阅读全文
0 0
原创粉丝点击