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面向对象
    Python基本数据类型
    小刘同学的第一百四十四篇博文
    小刘同学的第一百四十三篇日记
    小刘同学的第一百四十二篇日记
    小刘同学的第一百四十一篇日记
    小刘同学的第一百四十篇日记
    小刘同学的第一百三十九篇博文
    小刘同学的第一百三十八篇日记
    小刘同学的第一百三十七篇日记
  • 原文地址:https://www.cnblogs.com/baocong/p/6663500.html
Copyright © 2011-2022 走看看