zoj 2676 Network Wars 最小割+0-1分数规划

题目链接: http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2676

题意:

给出N个点和M条边,要求一个割集,使得集合中 ans = 所有边点权值和/边的数量 最小。

思路:

0-1分数规划。

具体证明参考 胡伯涛 《最小割模型在信息学竞赛中的应用

设g = min(Σwi/Σ1)

转化为 求g使得 (Σwi - g*Σ1) = 0。

所以二分求g的值。

每次建图的时候,以1为源点,N为汇点。

原来图中每条边的容量 = wi-g。

要注意点是如果容量<0,那么这条边必在割集中。

如果容量>=0,在图中连起来然后求最小割。

最后输出边集。

  1 #include <iostream>
  2 #include <cstring>
  3 #include <string>
  4 #include <cstdio>
  5 #include <queue>
  6 #include <cmath>
  7 #include <algorithm>
  8 #include <vector>
  9 using namespace std;
 10 #define maxn 105
 11 const double inf = 10000007;
 12 const double eps = 1e-8;
 13 struct Edge
 14 {
 15     int from, to, xh;
 16     double cap, flow;
 17     Edge(int f, int t, double c, double fl, int x)
 18     {
 19         from = f; to = t; cap = c; flow = fl; xh = x;
 20     }
 21 };
 22 struct Edge2
 23 {
 24     int from, to;
 25     double cost;
 26 }init[405];
 27 vector <Edge> edges;
 28 vector <int> G[maxn];
 29 int n, m, s, t;
 30 int vis[maxn], cur[maxn], d[maxn];
 31 double min(double a, double b)
 32 {
 33     return a<b?a:b;
 34 }
 35 void AddEdge(int from, int to, double cap, int xh)
 36 {
 37     edges.push_back(Edge(from, to, cap, 0, xh));
 38     edges.push_back(Edge(to, from, 0, 0, -1));
 39     m = edges.size();
 40     G[from].push_back(m-2);
 41     G[to].push_back(m-1);
 42 }
 43 bool bfs()
 44 {
 45     memset(vis, 0, sizeof(vis));
 46     d[s] = 0;
 47     vis[s] = 1;
 48     queue <int> q;
 49     q.push(s);
 50     while(!q.empty())
 51     {
 52         int u = q.front(); q.pop();
 53         for(int i = 0; i < G[u].size(); i++)
 54         {
 55             Edge &e = edges[G[u][i]];
 56             if(!vis[e.to] && e.cap-e.flow > eps)
 57             {
 58                 vis[e.to] = 1; 
 59                 d[e.to] = d[u]+1;
 60                 q.push(e.to);
 61             }
 62         }
 63     }
 64     return vis[t];
 65 }
 66 double dfs(int x, double a)
 67 {
 68     if(x == t || fabs(a) <eps) return a;
 69     double flow = 0, f;
 70     for(int &i = cur[x]; i < G[x].size(); i++)
 71     {
 72         Edge &e = edges[G[x][i]];
 73         if(d[x]+1 == d[e.to] && (f = dfs(e.to, min(a, e.cap - e.flow))) > eps)
 74         {
 75             e.flow += f;
 76             edges[G[x][i]^1].flow -= f;
 77             flow += f;
 78             a -= f;
 79             if(fabs(a) < eps) break;
 80         }
 81     }
 82     return flow;
 83 }
 84 double Maxflow()
 85 {
 86     double flow = 0;
 87     while(bfs())
 88     {
 89         memset(cur, 0, sizeof(cur));
 90         flow += dfs(s, inf);
 91     }
 92     return flow;
 93 }
 94 int N, M;
 95 int main()
 96 {
 97     while(~scanf("%d%d", &N, &M))
 98     {
 99         for(int i = 1; i <= M; i++)
100         {
101             scanf("%d%d%lf", &init[i].from, &init[i].to, &init[i].cost);
102         }
103         double l = 0, r = 10000001;
104         s = 1, t = N; n = N;
105         double mid;
106         double sum = 0;
107         while(l+eps <= r)
108         {
109             edges.clear();
110             for(int i = 1; i <= N; i++) G[i].clear();
111             mid = (l+r)/2.0;
112             sum = 0;
113             for(int i = 1; i <= M; i++)
114             {
115                 double temp = init[i].cost - mid;
116                 if(temp < 0) sum += temp;
117                 else
118                 {
119                     AddEdge(init[i].from, init[i].to, temp, i);
120                     AddEdge(init[i].to, init[i].from, temp, i);
121                 }
122             }
123             sum += Maxflow();
124             if(sum >= eps) l = mid;
125             else r = mid;
126         }
127         vector <int> ans;
128         edges.clear();
129         for(int i = 1; i <= N; i++) G[i].clear();
130         for(int i = 1; i <= M; i++)
131         {
132             double temp = init[i].cost - mid;
133             if(temp >= 0)
134             {
135                 AddEdge(init[i].from, init[i].to, temp, i);
136                 AddEdge(init[i].to, init[i].from, temp, i);
137             }
138         }
139         Maxflow();
140         int cnt = 0;
141         for(int i = 1; i <= M; i++)
142         {
143             if((vis[init[i].from] + vis[init[i].to]) == 1 || init[i].cost + eps < mid)
144             {
145                 cnt++;
146             }
147         }
148         printf("%d\n", cnt);
149         bool flag = true;
150         for(int i = 1; i <= M; i++)
151         {
152             if((vis[init[i].from] + vis[init[i].to]) == 1 || init[i].cost + eps < mid)
153             {
154                 if(flag)
155                 {
156                     printf("%d", i);
157                     flag = false;
158                 }
159                 else printf(" %d", i);
160             }
161         }
162         printf("\n");
163         
164     }
165 
166     return 0;
167 }

 

posted @ 2015-08-05 16:31  下周LGD该赢了吧  阅读(170)  评论(0编辑  收藏  举报