题目详解出自 论文 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 ;
}

最新文章

  1. 在Win7 64位操作系统下安装Oracle 10g
  2. Java学习2 - JDK和JRE和JVM的区别_JDK的下载安装_环境变量配置
  3. codeforces 101C C. Vectors(数学)
  4. Objective-c复制对象的概念
  5. 哈哈,好像swift 以后有可能用来开发安卓喔
  6. 如何使用css和jquery控制文章标题字数?
  7. AutoCAD按坐标打印图纸
  8. linux系统学习(常用命令)
  9. 7zip self-extracted executable: To extract file to specific directory
  10. haporoxy的keeplaive ZZ
  11. spring mvc mybatis
  12. spring的CXF远程服务
  13. Hadoop2.4.1伪分布式安装
  14. Win7下 Python中文正则的奇异表现
  15. mysql MHA高可用测试
  16. 同一个服务器部署两个Tomcat并用Nginx实现反向代理
  17. 巧用 即刻搜索事件 input propertychange 监听输入框字数
  18. 查看Ubuntu的显卡信息
  19. 学习笔记58—3D杯子设计
  20. socket网络编程扫盲篇

热门文章

  1. Win7下telnet使用
  2. [原]unity3D 相机跟随
  3. IOS 应用官方接口地址
  4. 关于WPF自定义控件(导航)
  5. iOS 图片剪切和压缩的几个方法
  6. 在SELECT DISTINCT 状况下使用 Order BY Newid() 随机数选出记录
  7. Java使用dom4j读取xml时报错:org.dom4j.DocumentException: Error on line 2 of document : Invalid byte 2 of 2-byte UTF-8 sequence. Nested exception: Invalid byte 2 of 2-byte UTF-8 sequence
  8. VS2015编译提示无法运行“rc.exe”
  9. 关于Android不能启动的问题
  10. [NodeJS] Node.js 与 V8 的故事