【POJ2125】Destroying The Graph(最小权覆盖点集)

来源:互联网 发布:宝宝照片创意软件 编辑:程序博客网 时间:2024/05/17 06:09

记录一个菜逼的成长。。

题目链接

题目大意:

这里写图片描述
求最小代价,并且输出一个方案

求最小代价

将一个点v拆成两个点va,vb
c(s,va)=ca(v)
c(vb,t)=cb(v)
c(ua,vb)=INF
按上述建边,最小割就是最小的代价。

输出方案:

从源点s开始dfs,如果到点v的边没有满流,则说明点v不是被选择删除所有出边的,标记v点。
这样标记后,如果连接s点的点是没有被标记的,则说明是被选择删除所有出边的点。
如果连接t点的点是被标记的,则说明是被选择删除所有入边的点。
因为如果连接t点的vb点是被标记的,则说明存在连接vb的点没有满流,由于覆盖点集的定义,vb肯定是被选择删除所有入边的点。

在这个论文里算法合集之《最小割模型在信息学竞赛中的应用》同样有详细的解释

#include <stdio.h>#include <string.h>#include <vector>#include <queue>#include <algorithm>using namespace std;#define rep(i,l,r) for( int i = l; i <= r; i++ )#define rep0(i,l,r) for( int i = l; i < r; i++ )#define ALL(v) (v).begin(),(v).end()#define cl(a,b) memset(a,b,sizeof(a))#define clr clear()#define pb push_back#define mp make_pair#define fi first#define se secondconst int INF = 0x3f3f3f3f;const int MAX_V = 1000 + 10;struct edge{  int to,cap,rev,flow;  edge(){}  edge(int _to,int _cap,int _rev,int _flow):to(_to),cap(_cap),rev(_rev),flow(_flow){}};vector<edge>G[MAX_V];int level[MAX_V];int iter[MAX_V];void add(int from,int to,int cap,int flow = 0){  G[from].push_back(edge(to,cap,G[to].size(),0));  G[to].push_back(edge(from,0,G[from].size()-1,0));}void bfs(int s){  memset(level,-1,sizeof(level));  queue<int>que;  level[s] = 0;  que.push(s);  while(!que.empty()){    int f = que.front();    que.pop();    for( int i = 0; i < G[f].size(); i++ ){      edge &e = G[f][i];      if(e.cap > 0 && level[e.to] == -1){        level[e.to] = level[f] + 1;        que.push(e.to);      }    }  }}int dfs(int v,int t,int f){  if(v == t)return f;  for( int &i = iter[v]; i < G[v].size(); i++ ){    edge &e = G[v][i];    if(e.cap > 0 && level[v] < level[e.to]){      int d = dfs(e.to,t,min(e.cap,f));      if(d > 0){        e.cap -= d;e.flow += d;        G[e.to][e.rev].cap += d;        return d;      }    }  }  return 0;}int max_flow(int s,int t){  int flow = 0;  for(;;){    bfs(s);    if(level[t] == -1)return flow;    memset(iter,0,sizeof(iter));    int f;    while((f = dfs(s,t,INF)) > 0)      flow += f;  }}int vis[MAX_V];void dfs1(int x){  vis[x] = 1;  rep0(i,0,G[x].size()){    int v = G[x][i].to;    if(!vis[v] && G[x][i].cap != 0)dfs1(v);  }}int main(){  int n,m;  while(~scanf("%d%d",&n,&m)){    int s = 0,t = n + n + 1,x;    rep(i,s,t)G[i].clr;    rep(i,1,n)scanf("%d",&x),add(i+n,t,x);    rep(i,1,n)scanf("%d",&x),add(s,i,x);    rep(i,1,m){      int u,v;      scanf("%d%d",&u,&v);      add(u,v+n,INF);    }    printf("%d\n",max_flow(s,t));    int cnt = 0;    vector<int>ans[MAX_V];    cl(vis,0);    dfs1(s);    rep0(i,0,G[s].size()){      int v = G[s][i].to;      if(!vis[v])ans[v].pb(0),cnt++;    }    rep0(i,0,G[t].size()){      int v = G[t][i].to;      if(vis[v])ans[v-n].pb(1),cnt++;    }    printf("%d\n",cnt);    rep(i,1,n){      rep0(j,0,ans[i].size()){        if(ans[i][j])printf("%d +\n",i);        else printf("%d -\n",i);      }    }  }  return 0;}
原创粉丝点击