zoukankan      html  css  js  c++  java
  • POJ 3155 最大密度子图

    链接:

    http://poj.org/problem?id=3155

    题解:

    要最大化下式:

    可以用二分求解以下分数规划问题:

    也就是最大化:

    设子图为G'=(V', E')。如果边(u,v)∈E',那么必有u,v属于V'。把点权设为负值的话,问题可以转换为求最大权闭合图(POJ 2987 Firing)。

    又因为点固定时,边越多越好。所以转换思路,不是边E'决定点集V',而应该反过来。当选定点集V'后,V'内部两两之间能构成的边就是最佳的E'。那么由V'发出的,不在E'内部的那些边构成了一个割集,当此割集最小时,E'最大。问题归结于求解最小割。

    上图g为答案的猜测值,d为度数(出度+入度),c为割集(V'和V'补集构成的边)。

    此时构图方式:

    即是将原图 G(E) 转化为网络 = (VE) 的过程:在原图点集的基础上增加源 和汇 ;将每条原无向边 (u,v) 替换为两条容量为1的有向边uv  v,u  ;增加连接源 到原图每个点 的有向边sv  ,容量为;增加连接原图每个点 到汇 的有向边vt   ,容量为 (+ 2dv ) 。

    代码:

      1 #include <map>
      2 #include <set>
      3 #include <cmath>
      4 #include <queue>
      5 #include <stack>
      6 #include <cstdio>
      7 #include <string>
      8 #include <vector>
      9 #include <cstdlib>
     10 #include <cstring>
     11 #include <sstream>
     12 #include <iostream>
     13 #include <algorithm>
     14 #include <functional>
     15 using namespace std;
     16 #define rep(i,a,n) for (int i=a;i<n;i++)
     17 #define per(i,a,n) for (int i=n-1;i>=a;i--)
     18 #define pb push_back
     19 #define mp make_pair
     20 #define all(x) (x).begin(),(x).end()
     21 #define SZ(x) ((int)(x).size())
     22 typedef vector<int> VI;
     23 typedef long long ll;
     24 typedef pair<int, int> PII;
     25 const ll mod = 1e9 + 7;
     26 const int inf = 0x3f3f3f3f;
     27 const double eps = 1e-10;
     28 const double pi = acos(-1.0);
     29 // head
     30 
     31 struct edge { int to; double cap; int rev; };
     32 const int MAX_V = 110;
     33 vector<edge> G[MAX_V];
     34 int level[MAX_V];
     35 int iter[MAX_V];
     36 
     37 void add_edge(int from, int to, double cap) {
     38     G[from].pb(edge{ to, cap, (int)G[to].size() });
     39     G[to].pb(edge{ from, 0, (int)G[from].size() - 1 });
     40 }
     41 
     42 void bfs(int s) {
     43     memset(level, -1, sizeof(level));
     44     queue<int> que;
     45     level[s] = 0;
     46     que.push(s);
     47     while (!que.empty()) {
     48         int v = que.front(); que.pop();
     49         rep(i, 0, G[v].size()) {
     50             edge &e = G[v][i];
     51             if (e.cap > 0 && level[e.to] < 0) {
     52                 level[e.to] = level[v] + 1;
     53                 que.push(e.to);
     54             }
     55         }
     56     }
     57 }
     58 
     59 double dfs(int v, int t, double f) {
     60     if (v == t) return f;
     61     for (int &i = iter[v]; i < G[v].size(); i++) {
     62         edge &e = G[v][i];
     63         if (e.cap > 0 && level[v] < level[e.to]) {
     64             double d = dfs(e.to, t, min(f, e.cap));
     65             if (d > 0) {
     66                 e.cap -= d;
     67                 G[e.to][e.rev].cap += d;
     68                 return d;
     69             }
     70         }
     71     }
     72     return 0;
     73 }
     74 
     75 double max_flow(int s, int t) {
     76     double flow = 0;
     77     while (1) {
     78         bfs(s);
     79         if (level[t] < 0) return flow;
     80         memset(iter, 0, sizeof(iter));
     81         double f;
     82         while ((f = dfs(s, t, inf)) > 0) flow += f;
     83     }
     84 }
     85 
     86 struct Rel { int x, y; }p[1010];
     87 int degree[MAX_V];
     88 int n, m, s, t;
     89 
     90 void construct_graph(double mid) {
     91     rep(i, 0, MAX_V) G[i].clear();
     92     rep(i, 1, n + 1) add_edge(s, i, m), add_edge(i, t, m + 2 * mid - degree[i]);
     93     rep(i, 0, m) add_edge(p[i].x, p[i].y, 1.0), add_edge(p[i].y, p[i].x, 1.0);
     94 }
     95 
     96 int vis[MAX_V], sum;
     97 void dfs_travel(int v) {
     98     sum++;
     99     vis[v] = 1;
    100     rep(i, 0, G[v].size()){
    101         edge &e = G[v][i];
    102         if (e.cap > eps && !vis[e.to]) dfs_travel(e.to);
    103     }
    104 }
    105 
    106 int main() {
    107     cin >> n >> m;
    108     if (m == 0) return puts("1
    1"), 0;
    109     s = 0, t = n + 1; 
    110     rep(i, 0, m) {
    111         scanf("%d%d", &p[i].x, &p[i].y);
    112         degree[p[i].x]++;
    113         degree[p[i].y]++;
    114     }
    115     double lb = 0, ub = m, precision = 1.0 / n / n;
    116     while (ub - lb >= precision) {
    117         double mid = (lb + ub) / 2;
    118         construct_graph(mid);
    119         double hg = (n*m - max_flow(s, t)) / 2;
    120         if (hg > eps) lb = mid;
    121         else ub = mid;
    122     }
    123     construct_graph(lb);
    124     max_flow(s, t);
    125     dfs_travel(0);
    126     cout << sum - 1 << endl;
    127     rep(i, 1, n + 1) if (vis[i]) cout << i << endl;
    128     return 0;
    129 }
  • 相关阅读:
    python中的编码问题
    CVPR2018 Tutorial 之 Visual Recognition and Beyond
    hdu 1376 Octal Fractions
    hdu 1329 Hanoi Tower Troubles Again!
    hdu 1309 Loansome Car Buyer
    hdu 1333 Smith Numbers
    hdu 1288 Hat's Tea
    hdu 1284 钱币兑换问题
    hdu 1275 两车追及或相遇问题
    hdu 1270 小希的数表
  • 原文地址:https://www.cnblogs.com/baocong/p/6663500.html
Copyright © 2011-2022 走看看