Network Wars

zoj2676:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1676

题意:给出一个带权无向图 ,每条边e有一个权 。求将点 和点t分开的一个边割集 ,使得该割集的平均边权最小,即最小化:

题解:转化成求0-1分数规划,然后求最小割,注意e‘<0是直接加入割边的,对剩余边求最小割即可。

  1 #include<iostream>
  2 #include<cstring>
  3 #include<algorithm>
  4 #include<cstdio>
  5 #include<queue>
  6 #include<cmath>
  7 #define INF 100000000
  8 using namespace std;
  9 const int N=1205;
 10 const int M=1000000;
 11 struct Node{
 12    int v;
 13    double f;
 14    int next;
 15 }edge[M];
 16 int n,m,u,v,cnt,sx,ex;
 17 int head[N],pre[N];
 18 int xx[N],yy[N];
 19 double cc[N];
 20 void init(){
 21     cnt=0;
 22     memset(head,-1,sizeof(head));
 23 }
 24 void add(int u,int v,double w){
 25     edge[cnt].v=v;
 26     edge[cnt].f=w;
 27     edge[cnt].next=head[u];
 28     head[u]=cnt++;
 29     edge[cnt].f=0;
 30     edge[cnt].v=u;
 31     edge[cnt].next=head[v];
 32     head[v]=cnt++;
 33 }
 34 bool BFS(){
 35   memset(pre,0,sizeof(pre));
 36   pre[sx]=1;
 37   queue<int>Q;
 38   Q.push(sx);
 39  while(!Q.empty()){
 40      int d=Q.front();
 41      Q.pop();
 42      for(int i=head[d];i!=-1;i=edge[i].next    ){
 43         if(edge[i].f&&!pre[edge[i].v]){
 44             pre[edge[i].v]=pre[d]+1;
 45             Q.push(edge[i].v);
 46         }
 47      }
 48   }
 49  return pre[ex]>0;
 50 }
 51 double dinic(double flow,int ps){
 52     double f=flow;
 53      if(ps==ex)return f;
 54      for(int i=head[ps];i!=-1;i=edge[i].next){
 55         if(edge[i].f&&pre[edge[i].v]==pre[ps]+1){
 56             double a=edge[i].f;
 57             double t=dinic(min(a,flow),edge[i].v);
 58               edge[i].f-=t;
 59               edge[i^1].f+=t;
 60             flow-=t;
 61              if(flow<=0)break;
 62         }
 63 
 64      }
 65       if(f-flow<=0)pre[ps]=-1;
 66       return f-flow;
 67 }
 68 double solve(){
 69     double sum=0;
 70     while(BFS())
 71         sum+=dinic(INF,sx);
 72     return sum;
 73 }
 74 bool ok(double mid){
 75     init();
 76     double flow=0;
 77     for(int i=1;i<=m;i++){
 78         if(cc[i]>mid){
 79             add(xx[i],yy[i],cc[i]-mid);
 80             add(yy[i],xx[i],cc[i]-mid);
 81         }
 82         else{
 83             flow+=cc[i]-mid;
 84         }
 85     }
 86     flow+=solve();
 87     if(flow>=0)return true;
 88     return false;
 89 }
 90 bool vis[N];
 91 void DFS(int u){
 92       for(int i=head[u];i!=-1;i=edge[i].next){
 93          int v=edge[i].v;
 94          if(!vis[v]&&edge[i].f>1e-5){
 95              vis[v]=1;
 96              DFS(v);
 97          }
 98       }
 99 }
100 int ans[N],top;
101 int main() {
102     int tt=1;
103     while(cin>>n>>m){
104         sx=1;
105         ex=n;
106         if(tt>1)puts("");
107         tt=2;
108         for(int i=1;i<=m;i++){
109             cin>>xx[i]>>yy[i]>>cc[i];
110         }
111         double l=0,r=1000000;
112       while(abs(l-r)>1e-5){
113           double mid=(l+r)/2;
114           if(ok(mid)){
115             l=mid;
116           }
117           else{
118             r=mid;
119           }
120       }
121         ok(r);
122        memset(vis,0,sizeof(vis));
123        vis[1]=1;
124        DFS(1);
125        top=0;
126        for(int i=1;i<=m;i++){
127           if(vis[xx[i]]+vis[yy[i]]==1||cc[i]<=r){
128              ans[++top]=i;
129           }
130        }
131        printf("%d\n",top);
132        sort(ans+1,ans+top+1);
133        for(int i=1;i<top;i++)
134         printf("%d ",ans[i]);
135        printf("%d\n",ans[top]);
136 
137     }
138     return 0;
139 }
View Code

 

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。