zoj2676--Network Wars(0-1分数规划+最小割)
来源:互联网 发布:led显示屏厂商 知乎 编辑:程序博客网 时间:2024/04/28 03:58
zoj2676:题目链接
题目大意:有一个n个点的网络,其中有m条光缆(所有的点都被连接,任意两个点之间最多有一条,不存在连接自身的),每条光缆有一定的价值,网络中1为起点,n为终点,现在要求找出一些光缆能分割开1到n,使它们不能相互通信,并且要求花费的和除以光缆数的值最小。输出选择的光缆的编号。
从问题中可以看出一定是0-1分数规划的题目,假设选出光缆的集合M,M为原图的一个割,光缆si∈M,价值为ci,数量k = 1 ,可以推出g(x) = min( ∑c - x*∑k ),因为si是割中的边,将边的值转化为ci-x*k,那么g(x)为原图的最小割。这样就得到了单调关系,对于x的值进行二分,求最小割。求得当g(x)为0的时候的x,也就是花费的和除以光缆数的值最小。
求到x值以后,从1点进行搜索,找出所有能走到的点。如果一条边的两个点,一个被遍历到,一个没有被遍历到,那么这条边为一条割边。
#include <cstdio>#include <cstring>#include <cmath>#include <queue>#include <vector>#include <algorithm>using namespace std ;#define eqs 1e-9#define INF 0x3f3f3f3fstruct node{ int u , v ; double w ; int next , id ;}edge[2100] , p[600] ;int head[110] , cnt , id[110][110] ;int n , m , l[110] , vis[110] , flag[600] , num ;double sum[110][110] ;queue <int> que ;vector <int> vec ;void add(int u,int v,double w,int id) { edge[cnt].u = u ; edge[cnt].v = v ; edge[cnt].w = w ; edge[cnt].next = head[u] ; edge[cnt].id = id ; head[u] = cnt++ ; edge[cnt].u = v ; edge[cnt].v = u ; edge[cnt].w = 0 ; edge[cnt].next = head[v] ; edge[cnt].id = id ; head[v] = cnt++ ;}int bfs(int s,int t) { int u , v , i ; memset(l,-1,sizeof(l)) ; while( !que.empty() ) que.pop() ; que.push(s) ; l[s] = 0 ; while( !que.empty() ) { u = que.front() ; que.pop() ; for(i = head[u] ; i != -1 ; i = edge[i].next) { v = edge[i].v ; if( l[v] == -1 && edge[i].w >= eqs ) { l[v] = l[u] + 1 ; que.push(v) ; } } } if( l[t] > 0 ) return 1 ; return 0 ;}double dfs(int u,int t,double min1) { if( u == t ) return min1 ; int v , i ; double temp , ans = 0 ; for(i = head[u] ; i != -1 ; i = edge[i].next) { v = edge[i].v ; if( l[v] == l[u]+1 && edge[i].w >= eqs && ( temp = dfs(v,t,min(min1,edge[i].w) ) ) ) { edge[i].w -= temp ; edge[i^1].w += temp ; ans += temp ; min1 -= temp ; if( min1 < eqs ) break ; } } if( ans >= eqs ) return ans ; l[u] = -1 ; return 0 ;}double solve(double mid) { int i , j ; double ans = 0 , temp ; memset(head,-1,sizeof(head)) ; memset(flag,0,sizeof(flag)) ; cnt = num = 0 ; for(i = 0 ; i < m ; i++) { if( p[i].w - mid < 0 ){ flag[i] = 1 ; num++ ; ans += p[i].w-mid ; continue ; } add(p[i].u,p[i].v,p[i].w-mid,i) ; add(p[i].v,p[i].u,p[i].w-mid,i) ; } while( bfs(1,n) ) { while( (temp = dfs(1,n,INF) ) >= eqs ) ans += temp ; } return ans ;}void f_dfs(int u) { int i , v ; for(i = head[u] ; i != -1 ; i = edge[i].next) { v = edge[i].v ; if( vis[v] || edge[i].w < eqs ) continue ; vis[v] = 1 ; f_dfs(v) ; }}void f() { int i , u , v ; memset(vis,0,sizeof(vis)) ; vis[1] = 1 ; f_dfs(1) ; for(i = 0 ; i < cnt ; i += 2) { u = edge[i].u ; v = edge[i].v ; if( vis[u] && !vis[v] && edge[i].w < eqs && !flag[ id[u][v] ] ) { flag[ id[u][v] ] = 1 ; num++ ; } }}int main() { int i , j ; int u , v ; double w , low , mid , high , temp ; while( scanf("%d %d", &n, &m) != EOF ) { low = mid = high = 0.0 ; memset(head,-1,sizeof(head)) ; cnt = 0 ; for(i = 0 ; i < m ; i++) { scanf("%d %d %lf", &p[i].u, &p[i].v, &p[i].w) ; id[ p[i].u ][ p[i].v ] = id[ p[i].v ][ p[i].u ] = i ; high += p[i].w ; } while( high - low >= eqs ) { mid = (high + low) / 2.0 ; temp = solve(mid) ; if( fabs(temp) < eqs ) break ; if( temp < 0 ) high = mid ; else low = mid ; } f() ; printf("%d\n", num) ; for(i = 0 ; i < m && num ; i++) { if( !flag[i] ) continue ; num-- ; if( num ) printf("%d ", i+1) ; else printf("%d\n", i+1) ; } printf("\n") ; } return 0 ;}
1 0
- zoj2676--Network Wars(0-1分数规划+最小割)
- zoj2676 Network Wars 0-1分数规划 最小割的应用
- 【ZOJ2676】Network Wars 最小割+01分数规划
- Network Wars-ZOJ2676最小割+01规划
- zoj2676 Network Wars(0-1分数规划,最大流模板)
- 0-1分数规划 网络流 最小割 最大流最小割 zoj2676 network
- Gym 100204G Network Wars(最小割+0/1分数规划)
- zoj 2676 Network Wars(01分数规划+最小割)
- ZOJ-2676-Network Wars(01分数规划+最小割)
- zoj2676 Network Wars (01分数规划)
- zoj 2676 Network Wars 【0-1分数规划 + 最小割】 【吃一堑长一智】
- [ZJU 2676]Network Wars(分数规划+最小割)
- zoj 2676 Network Wars(最小割,01分数规划)
- 【ZOJ】2676 Network Wars 01分数规划+最小割
- ZOJ 2676 Network Wars 最小割 分数规划
- cogs 2047. [ZOJ2676]网络战争 (最小割+01分数规划)
- 【最小割模型、01分数规划】zoj2676Network Wars
- ZOJ2676 Network Wars
- RS232转串口读不出数据常见原因
- 软考,是结束,也是另一个开始
- OrCAD图文教程:把一个元件分多个部分画出来
- Linux常用命令集
- JAVA反射机制
- zoj2676--Network Wars(0-1分数规划+最小割)
- 掉进读书的兔子洞
- 二人雀神取消吃牌动作(参照听牌取消动作)
- vi编译器的三种模式
- 数学之最美公式
- Android 图片缓存之内存缓存技术LruCache,软引用
- leetcode--Populating Next Right Pointers in Each Node II
- HDU1325---Is It A Tree?
- JAVA 堆栈 堆 方法区 静态区 final static 内存分配 详解