题目详解出自 论文 Amber-最小割模型在信息学竞赛中的应用

题目大意: 给出一个带权无向图 G = (V,E), 每条边 e属于E都有一个权值We,求一个割边集C,使得该割边集的平均边权最小,即最小化:

1.  

将等式转换,引入x向量,Xi取值为(0,1),得到0-1分数规划常规式:

2.      

将其转换得到一个关于的一个函数:

3.      

其中为单调递减函数, 当且仅当  = 0 , 为最优值.

然后我们可以二分枚举最优值 , 然后判定当前最优值是否符合要求.

判定思路:  对于每一条边权Wi 变换成了新的边权 , 而向量X(x1,x2,..,xm)表示对应边取或者不取,所以根据其取与不取划分成一个ST集。

令取为1,则 函数就转换成了 最小割的容量了(即最大流)。

有个要注意的地方,一个是枚举的最优值是一个浮点数,还有就是当 < 0 时,必定是取得,因为它能使最优值尽可能小。

最终结果可以得出最优值后,然后在跑一次最大流,然后从源点S开始DFS标记所有可以访问到的顶点,然后求出所有取得边。注意

 < 0 的边要特殊处理。因为是负值放进去计算不太方便。

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<vector>
using namespace std; const int inf = 0x3f3f3f3f;
const int MAXN = ;
const double esp = 1e-;
int sign(double x){ return x<-esp?-:(x>esp);}
int n, m, Max;
int S, N, T; struct Edge{
int u, v, nxt;
double f;
}edge[];
struct Edge_Info{
int a,b,c;
void input(){
scanf("%d%d%d",&a,&b,&c);
}
}edge_info[];
bool vis[MAXN];
int h[MAXN], vh[MAXN];
int head[MAXN], idx; void AddEdge(int a,int b,double f){
edge[idx].u = a, edge[idx].v = b, edge[idx].f = f;
edge[idx].nxt = head[a], head[a] = idx++;
edge[idx].u = b, edge[idx].v = a, edge[idx].f = ;
edge[idx].nxt = head[b], head[b] = idx++;
}
double CreateGraph(double MaxW){
memset( head, -, sizeof(head));
idx = ;
double tmp_val = ;
for(int i = ; i <= m; i++){
int a = edge_info[i].a, b = edge_info[i].b, c = edge_info[i].c;
if( sign(c - MaxW) < )
tmp_val += c-MaxW;
else AddEdge(a,b,c-MaxW),AddEdge(b,a,c-MaxW);
}
return tmp_val;
}
double dfs(int u,double flow){
if(u == T) return flow;
int tmp = h[u]+; double sum = flow;
for(int i = head[u]; ~i; i = edge[i].nxt){
if( sign(edge[i].f) > && (h[ edge[i].v ]+ == h[u])){
double p = dfs( edge[i].v, min(sum,edge[i].f));
edge[i].f -= p, edge[i^].f += p, sum -= p;
if( sign(sum)== || h[S]==N ) return flow-sum;
}
}
for(int i = head[u]; ~i; i = edge[i].nxt ){
if( sign(edge[i].f) > ) tmp = min(tmp,h[ edge[i].v ] );
}
if( --vh[ h[u] ] == ) h[S] = N;
else ++vh[ h[u]=tmp+ ];
return flow-sum;
}
double sap(){
double maxflow = ;
memset(h,,sizeof(h));
memset(vh,,sizeof(vh));
vh[] = N;
while( h[S] < N ) maxflow += dfs( S,inf );
return maxflow;
}
double Search( double l, double r ){
while( r-l > 1e- ){
double mid = (r+l)/2.0;
double maxflow = CreateGraph( mid );
maxflow += sap();
if( sign(maxflow) < ) r = mid;
else l = mid;
}
return l;
}
void DFS(int u){
vis[u] = true;
for(int i = head[u]; ~i; i = edge[i].nxt){
if( sign(edge[i].f) > && !vis[ edge[i].v ] )
DFS( edge[i].v );
}
} vector<int> res;
int mp[MAXN][MAXN]; void solve(){
S = , T = n, N = n;
double limit = Search( , Max );
double maxflow = CreateGraph( limit );
maxflow += sap();
res.clear();
memset(vis,,sizeof(vis));
DFS(S);
for(int i = ; i <= m; i++){
mp[ edge_info[i].a ][ edge_info[i].b ] = i;
mp[ edge_info[i].b ][ edge_info[i].a ] = i;
if( sign(edge_info[i].c-limit) < )
res.push_back(i);
}
for(int i = ; i < idx; i += ){ //
int u = edge[i].u, v = edge[i].v;
if( vis[u] && !vis[v] && sign( edge[i].f ) == ){ //
res.push_back( mp[u][v] );
}
}
sort( res.begin(), res.end() );
int num = res.size();
printf("%d\n", num );
for(int i = ; i < num; i++)
printf( i==? "%d":" %d", res[i] );
printf("\n");
}
int main(){
int Case = ;
while( scanf("%d%d",&n,&m) != EOF) {
Max = ;
for(int i = ; i <= m; i++){
edge_info[i].input();
Max = max( Max, edge_info[i].c );
}
solve();
if( Case++ > ) puts("");
}
return ;
}

zoj 2676 Network Wars 0-1分数规划+最小割的更多相关文章

  1. ZOJ 2676 Network Wars(最优比例最小割)

    Network Wars Time Limit: 5 Seconds      Memory Limit: 32768 KB      Special Judge Network of Bytelan ...

  2. ZOJ 2676 Network Wars[01分数规划]

    ZOJ Problem Set - 2676 Network Wars Time Limit: 5 Seconds      Memory Limit: 32768 KB      Special J ...

  3. ZOJ 2676 Network Wars ★(最小割算法介绍 && 01分数规划)

    [题意]给出一个带权无向图,求割集,且割集的平均边权最小. [分析] 先尝试着用更一般的形式重新叙述本问题.设向量w表示边的权值,令向量c=(1, 1, 1, --, 1)表示选边的代价,于是原问题等 ...

  4. ZOJ 2676 Network Wars(网络流+分数规划)

    传送门 题意:求无向图割集中平均边权最小的集合. 论文<最小割模型在信息学竞赛中的应用>原题. 分数规划.每一条边取上的代价为1. #include <bits/stdc++.h&g ...

  5. HDU 2676 Network Wars 01分数规划,最小割 难度:4

    http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1676 对顶点i,j,起点s=1,终点t=n,可以认为题意要求一组01矩阵use ...

  6. 【BZOJ3232】圈地游戏 分数规划+最小割

    [BZOJ3232]圈地游戏 Description DZY家的后院有一块地,由N行M列的方格组成,格子内种的菜有一定的价值,并且每一条单位长度的格线有一定的费用. DZY喜欢在地里散步.他总是从任意 ...

  7. bzoj 3232: 圈地游戏【分数规划+最小割】

    数组开小导致TTTTTLE-- 是分数规划,设sm为所有格子价值和,二分出mid之后,用最小割来判断,也就是判断sm-dinic()>=0 这个最小割比较像最大权闭合子图,建图是s像所有点连流量 ...

  8. bzoj 3232 圈地游戏 —— 01分数规划+最小割建图(最大权闭合子图)

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3232 心烦意乱的时候调这道题真是...越调越气,就这样过了一晚上... 今天再认真看看,找出 ...

  9. 【洛谷P2494】 [SDOI2011]保密(分数规划+最小割)

    洛谷 题意: 题意好绕好绕...不想写了. 思路: 首先类似于分数规划做法,二分答案得到到每个点的最小危险度. 然后就是在一个二分图中,两边撤掉最少的点(相应代价为上面算出的危险度)及相应边,使得中间 ...

随机推荐

  1. python字符串 分片索引

    字符串是字符的有序集合,可以通过其位置来获得具体的元素.在python中,字符串中的字符是通过索引来提取的,索引从0开始. python可以取负值,表示从末尾提取,最后一个为-1,倒数第二个为-2,即 ...

  2. phpcms列表页调用 点击量

    很多朋友经常问Phpcms v9的首页.列表页.内容页点击量如何调用.现在就给大家分享phpcms V9如何分别在首页.列表页.内容页调用点击量代码: 1. Phpcms v9首页调用点击量{pc:c ...

  3. C# 多线程 Parallel.ForEach 和 ForEach 效率问题研究及理解

    from:https://blog.csdn.net/li315171406/article/details/78450534 最近要做一个大数据dataTable循环操作,开始发现 运用foreac ...

  4. Floyd 和 bellman 算法

    Floyd-Warshall算法(Floyd-Warshall algorithm)是解决任意两点间的最短路径的一种算法,可以正确处理有向图或负权的最短路径问题,同时也被用于计算有向图的传递闭包. F ...

  5. Centos6.3 下使用 Tomcat-6.0.43 非root用户 部署 生产环境 端口转发方式

    一.安装JDK环境 方法一. 官方下载链接 http://www.oracle.com/technetwork/java/javase/downloads/jdk7-downloads-1880260 ...

  6. iOS Ad hoc

    There's one situation in which you need an Ad Hoc profile, and that's when you want to test Push Not ...

  7. GSAP JS基础教程--认识GSAP JS

    第一次写博文呢,这次写博客是因为应一位同学的要求,写一下GSAP JS的一个小教程.为什么说小呢?因为它实际上就是小,只是一个入门级的小教程.如果你想问:“那你为什么不写详细一点呢?”,我想说,说., ...

  8. 一句话木马:ASPX篇

    aspx木马收集: <%@ Page Language="Jscript"%><%eval(Request.Item["chopper"],& ...

  9. HttpClient 通信工具类

    package com.taotao.web.service; import java.util.ArrayList; import java.util.List; import java.util. ...

  10. 使用composer进行依赖管理:以guzzle为例

    今天突然发现一个不错的php http客户端库guzzle,欣喜不已,跃跃欲试.打开guzzle文档,发现需要composer做依赖管理.之前没有接触过composer,正好以此学习下,也蛮好! 本文 ...