题目详解出自 论文 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. java程序员如何编写更好的单元测试的7个技巧

    详解 cppunit进行单元测试 单元测试(模块测试)是开发者编写的一小段代码,用于检验被测代码的一个很小的.很明确的功能是否正确.通常而言,一个单元测试是用于判断某个特定条件(或者场景)下某个特定函 ...

  2. HTML5 标准规范完成了

    ​    ​万维网联盟(W3C)昨天宣布,HTML5 标准规范终于最终制定完成了,并已公开发布.对于前端工程师来说,这无疑是一个振奋人心的好消息. ​    ​众所周知,HTML5改变了互联网,将成为 ...

  3. android studio 导入第三方库的记录

    android studio 导入第三方库的记录.jar包 和 库 一.jar包 1.jar包的话很简单,首先换成project模式,将你要用的jar包复制到lib下面.如图 2.然后右键选择Add ...

  4. 启用sharepoin2013中的ChartWebPart

    首先看一张sharepoint2013中ChartWebPart的效果图. 在sharepoint2010中加入了一个新的webpart,叫ChartWebPart,提供了对数据的图表展示,可以对数据 ...

  5. SaltStack salt-run 命令

    salt-run 常见用法如下: salt-run manage.up # 查看在线的minion salt-run manage.down # 查看不在线的minion salt-run manag ...

  6. Memcached 运行状态

    memcached-tool 命令用于查看 Memcached 运行状态,用法如下: Usage: memcached-tool <host[:port] | /path/to/socket&g ...

  7. Unity透明Shader

    Shader "Custom/Blocks" { Properties { _Color (,,,) _MainTex ("Albedo (RGB)", 2D) ...

  8. 处理i18n国际电话区号的代码实践

    本文转载至 http://adad184.com/2015/08/18/practice-in-i18n-dialling-code/ 前言 上周在忙产品的国际化(i18n)的问题 其中一个很重要的地 ...

  9. 剑指offer面试题7:用两个栈实现队列

    题目1:用两个栈来实现一个队列,完成队列的Push和Pop操作. 队列中的元素为int类型. 代码实现: public class Solution07 { Stack<Integer> ...

  10. React Native 入门到原理(详解)

    抛砖引玉(帮你更好的去理解怎么产生的 能做什么) 砖一.动态配置 由于 AppStore 审核周期的限制,如何动态的更改 app 成为了永恒的话题.无论采用何种方式,我们的流程总是可以归结为以下三部曲 ...