zoukankan      html  css  js  c++  java
  • poj 2125

    题意就是 有一个图, 两种操作,一种是删除某点的所有出边,一种是删除某点的所有入边,各个点的不同操作分别有一个花费,现在我们想把这个图的边都删除掉,需要的最小花费是多少

    那么本题的话,我们看到是要删除所有的边,但只需要在两个端点中的一端进行删除即可,这就可以联想到了最小点权覆盖了。

    一般对有向图而言,我们经常进行的就是拆点,将每个点拆成两个点,一个点是代表边从这出来,一个代表边从这进去。就分别对应了两种操作了。

    然后按照最小点权覆盖模型进行建图,求最大流。

    残余网络中从超级源开始深搜所有可达点。

    {A}中不可达的点就是应该执行1操作的点。 残余网络中,左侧不可达的点表示被操作1的流选中了

    {B}中可达的点就是应该执行2操作的点。 右侧可达的点表示从左侧开始无论如何也没有被流选中,只能留给操作2。

    最小点覆盖
      1 // File Name: 3308.cpp
      2 // Author: Missa
      3 // Created Time: 2013/4/17 星期三 11:24:48
      4 
      5 #include<iostream>
      6 #include<cstdio>
      7 #include<cstring>
      8 #include<algorithm>
      9 #include<cmath>
     10 #include<queue>
     11 #include<stack>
     12 #include<string>
     13 #include<vector>
     14 #include<cstdlib>
     15 #include<map>
     16 #include<set>
     17 using namespace std;
     18 #define CL(x,v) memset(x,v,sizeof(x));
     19 #define R(i,st,en) for(int i=st;i<en;++i)
     20 #define LL long long
     21 
     22 const int inf = 0x3f3f3f3f;
     23 const int maxn = 200+5;
     24 const int maxm = 45000;
     25 struct Edge
     26 {
     27     int v, next;
     28     int c;
     29 }p[maxm << 1];
     30 int head[maxn], e;
     31 int d[maxn], cur[maxn];
     32 int n, m, st, en;
     33 void init()
     34 {
     35     e = 0;
     36     //n = en;//记住n赋值为点的个数
     37     memset(head, -1, sizeof(head));
     38 }
     39 void addEdge(int u, int v, int c)
     40 {
     41     p[e].v = v; p[e].c = c;
     42     p[e].next = head[u]; head[u] = e++;
     43     swap(u,v);
     44     p[e].v = v; p[e].c = 0;
     45     p[e].next = head[u]; head[u] = e++;
     46 }
     47 int bfs(int st, int en)
     48 {
     49     queue <int > q;
     50     memset(d, 0, sizeof(d));
     51     d[st] = 1;
     52     q.push(st);
     53     while (!q.empty())
     54     {
     55         int u = q.front();q.pop();
     56         for (int i = head[u]; i != -1; i = p[i].next)
     57         {
     58             if (p[i].c > 0 && !d[p[i].v])
     59             {
     60                 d[p[i].v] = d[u] + 1;
     61                 q.push(p[i].v);
     62             }
     63         }
     64     }
     65     //for (int i = 0; i <= n; i ++)
     66     //    cout << d[i] << endl;
     67     return d[en];
     68 }
     69 int dfs(int u, int a)
     70 {
     71     if (u == en || a == 0) return a;
     72     int f, flow = 0;
     73     for (int& i = cur[u]; i != -1; i = p[i].next)
     74     {
     75         if (d[u] + 1 == d[p[i].v] && (f = dfs(p[i].v, min(a, p[i].c))) > 0)
     76         {
     77             p[i].c -= f;
     78             p[i^1].c += f;
     79             flow += f;
     80             a -= f;
     81             if (a == 0) break;
     82         }
     83     }
     84     return flow;
     85 }
     86 int dinic(int st, int en)
     87 {
     88     int ret = 0, tmp;
     89     while (bfs(st, en))
     90     {
     91         for (int i = 0; i <= n; ++i)
     92             cur[i] = head[i];
     93         ret += dfs(st, inf);
     94     //    cout << ret << endl;
     95     }
     96     return ret;
     97 }
     98 bool ok[maxn];
     99 void dfs(int u)
    100 {
    101     ok[u] = 1;
    102     for (int i = head[u]; i != -1; i = p[i].next)
    103     {
    104         int v = p[i].v;
    105         if (ok[v] == 0 && p[i].c)
    106             dfs(v);
    107     }
    108 }
    109 int main()
    110 {
    111     int c;
    112     while (~scanf("%d%d",&n, &m))
    113     {
    114         init();
    115         int tt = n;
    116         st = 0, en = (n << 1) + 1;
    117         for (int i = 1; i <= n; ++i)
    118         {
    119             scanf("%d", &c);
    120             addEdge(i + n, en,c);
    121         }
    122         for (int i = 1; i <= n; ++i)
    123         {
    124             scanf("%d", &c);
    125             addEdge(st, i, c);
    126         }
    127         for (int i = 1; i <= m; ++i)
    128         {
    129             int u,v;
    130             scanf("%d%d", &u,&v);
    131             addEdge(u, v + n, inf);
    132         }
    133         n = en;
    134         int ans = dinic(st, en);
    135         printf("%d\n",ans);
    136         memset(ok, 0, sizeof(ok));
    137         dfs(st);
    138         int res = 0;
    139         for (int i = 1; i <= tt; ++i)
    140         {
    141             if (!ok[i])
    142                 res ++;
    143             if (ok[i + tt])
    144                 res ++;
    145         }
    146         printf("%d\n",res);
    147         for (int i = 1; i <= tt; ++i)
    148         {
    149             if (!ok[i])
    150                 printf("%d -\n",i);
    151             if (ok[i + tt])
    152                 printf("%d +\n",i);
    153         }
    154     }
    155     return 0;
    156 }
  • 相关阅读:
    pycharm安装,svn使用,远程开发调试,接口测试,连接服务器
    scrapy回调函数传递参数
    python发送邮件
    python开发部署时新增数据库中表的方法
    python更新数据库脚本三种方法
    python中json.loads,dumps,jsonify使用
    chmod 命令
    find
    find 命令
    locate 命令
  • 原文地址:https://www.cnblogs.com/Missa/p/3027348.html
Copyright © 2011-2022 走看看