zoj 2676 Network Wars 【0-1分数规划 + 最小割】 【吃一堑长一智】
2015-09-02 00:25
316 查看
Network Wars
Time Limit: 5 Seconds Memory Limit: 32768 KB Special Judge
Network of Byteland consists of n servers, connected by m optical cables. Each cable connects two servers and can transmit data in both directions. Two servers of the
network are especially important --- they are connected to global world network and president palace network respectively.
The server connected to the president palace network has number 1, and the server connected to the global world network has number n.
Recently the company Max Traffic has decided to take control over some cables so that it could see what data is transmitted by the president palace users. Of course they want
to control such set of cables, that it is impossible to download any data from the global network to the president palace without transmitting it over at least one of the cables from the set.
To put its plans into practice the company needs to buy corresponding cables from their current owners. Each cable has some cost. Since the company's main business is not spying, but
providing internet connection to home users, its management wants to make the operation a good investment. So it wants to buy such a set of cables, that cables mean cost} is minimal possible.
That is, if the company buys k cables of the total cost c, it wants to minimize the value of c/k.
<= n <= 100 , 1 <= m <= 400 ).
Next m lines describe cables~--- each cable is described with three integer numbers: servers
it connects and the cost of the cable. Cost of each cable is positive and does not exceed 107.
Any two servers are connected by at most one cable. No cable connects a server to itself. The network is guaranteed to be connected, it is possible to transmit data from any server to
any other one.
There is an empty line between each cases.
the number of cables to buy. After that output the cables to buy themselves. Cables are numbered starting from one in order they are given in the input file. There should an empty line between each cases.
Source: Andrew Stankevich's Contest #8
我是一个花了4小时错了2页然后AC这道题的人!!!
Segmentation Fault 只因为我mark数组开小了。。。
找了那么长长时间,真是醉了。吃一堑长一智 /(ㄒoㄒ)/~~
题意:给你一个N个点和M条边的图,已经给出每条边的边权。现在让你找出阻断1和N的一个边割集,要求边权平均值最小。最后答案输出任意一组边割集里面边的编号。
分析:题目需要求一个割,使得c / k最小。其中c为割集中所有边的权值之和,k为割集里面的边数。我们可以将问题转化为求f(x) = sigma(x * ci) / sigma(x
* 1)的最小值,(x == 0 || x == 1)
设o = sigma(xi * ci) / sigma(xi * 1) -> sigma(xi * ci) - sigma(xi * 1) * o = 0。
构造函数g(x) = min(
x * sigma(ci - o) )。
这样可以对于图中每一条边进行重赋权:c' = c - o。而g(x)就是在这个重新构造的图中求出一个s-t的最小割集。
再提一下g(x)函数,因为它的目的是取最小的加权和,所以在赋权时,对于负权的边则不用加入新图。可以明确的是这样的边一定属于边割集,而对于其它边则需要加入新图,然后跑一次最大流求出最小割。
特别的,在进行二分查找的过程中。
设o'是f(x)的最小值,则对于当前查找解mid
如果 t(mid) = 0 那么 ans = mid
如果 t(mid) < 0 那么 ans > mid
如果 t(mid) > 0 那么 ans < mid
今天大脑太累了,写个大概的解析。详细请看:点我看原版论文
写代码时注意精度!!!
累死了,该休息了。。。 (~﹃~)~zZ
AC代码:
Time Limit: 5 Seconds Memory Limit: 32768 KB Special Judge
Network of Byteland consists of n servers, connected by m optical cables. Each cable connects two servers and can transmit data in both directions. Two servers of the
network are especially important --- they are connected to global world network and president palace network respectively.
The server connected to the president palace network has number 1, and the server connected to the global world network has number n.
Recently the company Max Traffic has decided to take control over some cables so that it could see what data is transmitted by the president palace users. Of course they want
to control such set of cables, that it is impossible to download any data from the global network to the president palace without transmitting it over at least one of the cables from the set.
To put its plans into practice the company needs to buy corresponding cables from their current owners. Each cable has some cost. Since the company's main business is not spying, but
providing internet connection to home users, its management wants to make the operation a good investment. So it wants to buy such a set of cables, that cables mean cost} is minimal possible.
That is, if the company buys k cables of the total cost c, it wants to minimize the value of c/k.
Input
There are several test cases in the input. The first line of each case contains n and m (2<= n <= 100 , 1 <= m <= 400 ).
Next m lines describe cables~--- each cable is described with three integer numbers: servers
it connects and the cost of the cable. Cost of each cable is positive and does not exceed 107.
Any two servers are connected by at most one cable. No cable connects a server to itself. The network is guaranteed to be connected, it is possible to transmit data from any server to
any other one.
There is an empty line between each cases.
Output
First output k ---the number of cables to buy. After that output the cables to buy themselves. Cables are numbered starting from one in order they are given in the input file. There should an empty line between each cases.
Example
Input | Output |
6 8 1 2 3 1 3 3 2 4 2 2 5 2 3 4 2 3 5 2 5 6 3 4 6 3 | 4 3 4 5 6 |
4 5 1 2 2 1 3 2 2 3 1 2 4 2 3 4 2 | 3 1 2 3 |
我是一个花了4小时错了2页然后AC这道题的人!!!
Segmentation Fault 只因为我mark数组开小了。。。
找了那么长长时间,真是醉了。吃一堑长一智 /(ㄒoㄒ)/~~
题意:给你一个N个点和M条边的图,已经给出每条边的边权。现在让你找出阻断1和N的一个边割集,要求边权平均值最小。最后答案输出任意一组边割集里面边的编号。
分析:题目需要求一个割,使得c / k最小。其中c为割集中所有边的权值之和,k为割集里面的边数。我们可以将问题转化为求f(x) = sigma(x * ci) / sigma(x
* 1)的最小值,(x == 0 || x == 1)
设o = sigma(xi * ci) / sigma(xi * 1) -> sigma(xi * ci) - sigma(xi * 1) * o = 0。
构造函数g(x) = min(
x * sigma(ci - o) )。
这样可以对于图中每一条边进行重赋权:c' = c - o。而g(x)就是在这个重新构造的图中求出一个s-t的最小割集。
再提一下g(x)函数,因为它的目的是取最小的加权和,所以在赋权时,对于负权的边则不用加入新图。可以明确的是这样的边一定属于边割集,而对于其它边则需要加入新图,然后跑一次最大流求出最小割。
特别的,在进行二分查找的过程中。
设o'是f(x)的最小值,则对于当前查找解mid
如果 t(mid) = 0 那么 ans = mid
如果 t(mid) < 0 那么 ans > mid
如果 t(mid) > 0 那么 ans < mid
今天大脑太累了,写个大概的解析。详细请看:点我看原版论文
写代码时注意精度!!!
累死了,该休息了。。。 (~﹃~)~zZ
AC代码:
#include <cstdio> #include <cstring> #include <cstdlib> #include <queue> #include <cmath> #include <algorithm> #define MAXN 110 #define MAXM 2000 #define INF 0x3f3f3f3f #define eps 1e-8 using namespace std; struct Edge { int from, to; double cap, flow; int ID, next; }; Edge edge[MAXM]; int head[MAXN], edgenum; int dist[MAXN], cur[MAXN]; bool vis[MAXN]; int N, M; struct rec { int from, to; double val; }; rec num[MAXM]; double Max; void input() { Max = 0; for(int i = 1; i <= M; i++) scanf("%d%d%lf", &num[i].from, &num[i].to, &num[i].val), Max = max(Max, num[i].val); } void init() { edgenum = 0; memset(head, -1, sizeof(head)); } void addEdge(int u, int v, double w, int id) { Edge E1 = {u, v, w, 0, id, head[u]}; edge[edgenum] = E1; head[u] = edgenum++; Edge E2 = {v, u, 0, 0, id, head[v]}; edge[edgenum] = E2; head[v] = edgenum++; } double ans;//记录总值 void getMap(double o) { ans = 0;//初始化 for(int i = 1; i <= M; i++) { double t = num[i].val - o; if(t > eps) addEdge(num[i].from, num[i].to, t, i), addEdge(num[i].to, num[i].from, t, i); else ans += t;//该边就是割边 } } bool BFS(int s, int t) { queue<int> Q; memset(dist, -1, sizeof(dist)); memset(vis, false, sizeof(vis)); dist[s] = 0; vis[s] = true; Q.push(s); while(!Q.empty()) { int u = Q.front(); Q.pop(); for(int i = head[u]; i != -1; i = edge[i].next) { Edge E = edge[i]; if(!vis[E.to] && E.cap - E.flow > eps) { dist[E.to] = dist[u] + 1; if(E.to == t) return true; vis[E.to] = true; Q.push(E.to); } } } return false; } double DFS(int x, double a, int t) { if(x == t || fabs(a) < eps) return a;//精度 double flow = 0, f; for(int &i = cur[x]; i != -1; i = edge[i].next) { Edge &E = edge[i]; if(dist[E.to] == dist[x] + 1 && (f = DFS(E.to, min(a, E.cap-E.flow), t)) > eps) { edge[i].flow += f; edge[i^1].flow -= f; flow += f; a -= f; if(fabs(a) < eps) break;//精度 } } return flow; } double Maxflow(int s, int t) { double flow = 0; while(BFS(s, t)) { memcpy(cur, head, sizeof(head)); flow += DFS(s, Max, t); } return flow; } void find_S(int u)//找源点能到的点集 S { vis[u] = true; for(int i = head[u]; i != -1; i = edge[i].next) { Edge E = edge[i]; if(vis[E.to]) continue; if(E.cap - E.flow > eps) find_S(E.to); } } bool mark[MAXM];//标记该边是否是 选中最小割的边 int sum;//记录最小割里面 的边数 void solve() { double l = 0, r = Max, mid; while(r - l >= eps) { mid = (l + r) / 2; init(); getMap(mid);//每次根据mid值 重建图 ans += Maxflow(1, N);//求一次最小割 if(ans > eps) l = mid; else r = mid; } memset(vis, false, sizeof(vis)); find_S(1);//找源点能到 的点集S集 sum = 0;//总边数 memset(mark, false, sizeof(mark)); for(int i = 1; i <= M; i++) { if((vis[num[i].from] && !vis[num[i].to]) || (!vis[num[i].from] && vis[num[i].to]) || num[i].val <= mid) sum++, mark[i] = true; } printf("%d\n", sum); int used = 0; for(int i = 1; i <= M; i++) { if(mark[i]) { if(used) printf(" "); printf("%d", i); used++; } } printf("\n"); } int main() { int k = 0; while(scanf("%d%d", &N, &M) != EOF) { if(k) printf("\n"); k++; input(); solve(); } return 0; }
相关文章推荐
- C#StringBuilder的使用
- CCFontAtlasCache,CCFontCharMap,CCFontFNT,CCFontFreeType解析
- [Leetcode 264] Ugly Number II
- UVALive 3211 Now or Later (2-SAT)
- idea安装go插件
- HDU 1712 ACboy needs your help(泛化物品dp)
- c/c++使用gsoap调用wcf发布的webservice
- 【Java】Beanutils-No destination bean specified问题分析
- MySQL 取得两个时间相差的分钟数 及 常用时间函数
- 把/root/目录下的所有目录拷贝到/tmp/
- Asp.mvc ~ 使用AngularJs构建SPA
- 二次元社交应用 JUJU 获 580 万美金 A 轮融资,在 6 线城市都有
- TFT显示汉字
- VS2010调试DLL
- Sublime Text 3 常用插件以及安装方法
- c/c++使用gsoap发布和调用webservice
- hdu 3524 Perfect Squares 快速幂+ 除法取余
- 《C#入门经典(第6版)》读书笔记4_第四章:流程控制
- 使用hmailserver搭建邮件服务器
- [Leetcode 263] Ugly Number