poj 2987 Firing 最大权闭合图

来源:互联网 发布:4g通信软件 编辑:程序博客网 时间:2024/05/21 19:58

题意:

       裸的最大权闭合图。

分析:

       国家集训队论文<<最小割模型在信息学竞赛中的应用>>里有完整的建模推导证明,建议搜了学习下~这里直接用dinic搞了。

代码:

//poj 2987//sep9#include <iostream>  #include <queue>   using namespace std;typedef long long INT;  const INT MAXN=5000;  const INT MAXM=60000; const INT MAX=INT_MAX*(INT)(INT_MAX-3);    struct Edge    {        INT v,nxt,f;    }e[MAXM*2+10];    queue<INT> que;    INT src,sink;    INT g[MAXN+10];    INT nume;    bool vis[MAXN+10];    INT dist[MAXN+10];    INT n,m,vertex_cnt;void addedge(INT u,INT v,INT c)    {        e[++nume].v=v;e[nume].f=c;e[nume].nxt=g[u];g[u]=nume;        e[++nume].v=u;e[nume].f=0;e[nume].nxt=g[v];g[v]=nume;    }        void init()    {        memset(g,0,sizeof(g));          nume=1;    }        INT bfs()    {        while(!que.empty()) que.pop();        memset(dist,0,sizeof(dist));        memset(vis,0,sizeof(vis));        vis[src]=true;        que.push(src);          while(!que.empty()){            INT u=que.front();que.pop();            for(INT i=g[u];i;i=e[i].nxt)                if(e[i].f>0&&!vis[e[i].v]){                    que.push(e[i].v);                    dist[e[i].v]=dist[u]+1;                    vis[e[i].v]=true;                     if(e[i].v==sink)                        return 1;                }        }        return 0;    }        INT dfs(INT u,INT delta)    {        if(u==sink)            return delta;        INT ret=0;        for(INT i=g[u];ret<delta&&i;i=e[i].nxt)            if(e[i].f>0&&dist[e[i].v]==dist[u]+1){                INT dd=dfs(e[i].v,min(e[i].f,delta-ret));                if(dd>0){                    e[i].f-=dd;                    e[i^1].f+=dd;                    ret+=dd;                }                else                    dist[e[i].v]=-1;            }           return ret;    }        INT dinic()    {        INT ret=0;        while(bfs()==1)            ret+=dfs(src,MAX);        return ret;     }    void solve(INT u){++vertex_cnt;vis[u]=true; for(INT i=g[u];i;i=e[i].nxt)    if(e[i].f>0&&!vis[e[i].v])solve(e[i].v);}int main(){scanf("%lld%lld",&n,&m);INT W=0;init();src=0,sink=n+1; for(INT i=1;i<=n;++i){INT w;scanf("%lld",&w);if(w>0){W+=w;addedge(src,i,w);}else if(w<0){addedge(i,sink,-w);}}INT u,v;for(INT i=0;i<m;++i){scanf("%lld%lld",&u,&v);addedge(u,v,MAX);}INT max_profit = W - dinic();vertex_cnt=0;memset(vis,0,sizeof(vis));solve(src);printf("%lld %lld\n",vertex_cnt-1,max_profit);return 0;} 


0 0