当前位置: 代码迷 >> 综合 >> poj 2987 Firing 最大权闭合图
  详细解决方案

poj 2987 Firing 最大权闭合图

热度:84   发布时间:2024-01-19 05:24:46.0

题意:

       裸的最大权闭合图。

分析:

       国家集训队论文<<最小割模型在信息学竞赛中的应用>>里有完整的建模推导证明,建议搜了学习下~这里直接用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;
}