哈尔滨理工大学软件学院ACM程序设计全国邀请赛(网络同步赛)A Golds 最大流

来源:互联网 发布:秋水到底喜欢谁知乎 编辑:程序博客网 时间:2024/05/02 01:00

Golds

Description

Humans havediscovered a kind of new metal mineral on Mars which are distributed inpoint‐like with paths connecting each of them which formed a tree. There are Nmetal mineral. In i-th (1<=i<=N) metal mineral, there are a[i] golds. NowHumans launches m robots on Mars to collect golds. The i-th (1<=i<=m)robot can collect golds on path from s[i] to e[i], and at most collect w[i]golds. We want to know the maximum total golds that can be collected by mrobots.

 

 

Input

There are multiple cases in the input. 

In each case: 

The first linespecifies three integers N, m specifying the numbers of metal mineral and thenumber of robots. (1 <= N <= 2000, 1<=m<=2000)

The next line willgive N integers. a[i] (1<=i<=N) means there are a[i] golds on i-th metalmineral.(0 <= a[i] <= 10000)

The next n‐1 lines will givetwo integers u,v in each line specifying there is a path connected point u andv. (1<=u<=N, 1<=v<=N, u != v)

The next m lines will givethere integers s[i], e[i], w[i] in each line specifying the i-th robot cancollect golds on path from s[i] to e[i], and at most collect w[i] golds.

(1<=s[i]<=N, 1<=e[i]<=N,0<=w[i]<=20000000).

 

Output

For each case,output the maximum total golds that can be collected.

 

Sample Input

4 3

10 10 10 10

1  2

2  3

2 4

1 4 15

1  3 5

2  4 20

 

Sample Output

35 


题意:一棵树  n个点  每个点的金子数量  树的边  现在有m个机器人  每个机器人从u走到v  最多可收集c个金子  现在问所有机器人能收集金子的最大数量


题解:最大流  每个机器人dfs出可到的点的标号然后建边  最后建立源点和汇点跑最大流即可


#include<cstdio>#include<cstring>#include<queue>#include<cmath>using namespace std;const int Ni = 4005;const int MAX = 1<<30;struct Edge{    int u,v,c;    int next;}edge[8000005];int n,m;int edn;//边数int p[Ni];//父亲int d[Ni];int sp,tp;//原点,汇点struct node{int to,nex;}edges[4005];int head[2005],cnt=0;void addedge(int u,int v,int c)//最大流的边{    edge[edn].u=u; edge[edn].v=v; edge[edn].c=c;    edge[edn].next=p[u]; p[u]=edn++;edge[edn].u=v; edge[edn].v=u; edge[edn].c=0;    edge[edn].next=p[v]; p[v]=edn++;}int bfs(){    queue <int> q;    memset(d,-1,sizeof(d));    d[sp]=0;    q.push(sp);    while(!q.empty())    {        int cur=q.front();        q.pop();        for(int i=p[cur];i!=-1;i=edge[i].next)        {            int u=edge[i].v;            if(d[u]==-1 && edge[i].c>0)            {                d[u]=d[cur]+1;                q.push(u);            }        }    }    return d[tp] != -1;}int dfs(int a,int b){    int r=0;    if(a==tp)return b;    for(int i=p[a];i!=-1 && r<b;i=edge[i].next)    {        int u=edge[i].v;        if(edge[i].c>0 && d[u]==d[a]+1)        {            int x=min(edge[i].c,b-r);            x=dfs(u,x);            r+=x;            edge[i].c-=x;            edge[i^1].c+=x;        }    }    if(!r)d[a]=-2;    return r;}int dinic(int sp,int tp){    int total=0,t;    while(bfs())    {        while(t=dfs(sp,MAX))        total+=t;    }    return total;}void add(int u,int v){//树的边edges[cnt].to=v;edges[cnt].nex=head[u];head[u]=cnt++;}int num[2005],flag,zh[2005],q;void dfss(int u,int t,int v){//找路径if(t==v){flag=1;return ;}for(int i=head[t];~i;i=edges[i].nex){int d=edges[i].to;if(d!=u){zh[++q]=d;dfss(t,d,v);if(flag)return ;q--;}}}int main(){    int i,u,v,c,j;    while(~scanf("%d%d",&n,&m))    {        edn=0;//初始化        cnt=0;        memset(head,-1,sizeof(head));        memset(p,-1,sizeof(p));        for(i=1;i<=n;i++)scanf("%d",&num[i]);        for(i=1;i<n;i++){        scanf("%d%d",&u,&v);        add(u,v);        add(v,u);        }        for(i=1;i<=m;i++){        scanf("%d%d%d",&u,&v,&c);        flag=0;        q=0;        dfss(u,u,v);        addedge(2000+i,u,10000);//将每个机器人的点定为  i+2000        for(j=1;j<=q;j++){        addedge(2000+i,zh[j],10000);        }        addedge(0,2000+i,c);        }        for(i=1;i<=n;i++){        addedge(i,4002,num[i]);        }        sp=0;//源点是0        tp=4002;//汇点是4002        printf("%d\n",dinic(sp,tp));    }    return 0;}


0 0
原创粉丝点击