ZOJ 2676 分数规划

来源:互联网 发布:社交网络红包广告 编辑:程序博客网 时间:2024/05/16 01:37
zoj 2676 过了 sap的问题,准备找个好点的sap板子#include<iostream>#include<cstring>#include<string>#include<cstdio>#include<cstdlib>#include<algorithm>#define eps 1e-5#define maxn 500using namespace std;const int inf = 0x3f3f3f3f;const int MAXN = 110;const double esp = 1e-8;int sign(double x){ return x<-esp?-1:(x>esp);}int n, m, Max;int S, N, T;bool inde[maxn]; struct node    {        int u,v,cost;    }in[maxn];struct Edge{    int u, v, nxt;    double f;}edge[50101];struct Edge_Info{    int a,b,c;    void input(){        scanf("%d%d%d",&a,&b,&c);    }}edge_info[550];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 = 0;    edge[idx].nxt = head[b], head[b] = idx++;}double dfs(int u,double flow){    if(u == T) return flow;    int tmp = h[u]+1; double sum = flow;    for(int i = head[u]; ~i; i = edge[i].nxt){        if( sign(edge[i].f) > 0 && (h[ edge[i].v ]+1 == h[u])){            double p = dfs( edge[i].v, min(sum,edge[i].f));            edge[i].f -= p, edge[i^1].f += p, sum -= p;            if( sign(sum)==0 || h[S]==N ) return flow-sum;        }    }    for(int i = head[u]; ~i; i = edge[i].nxt ){        if( sign(edge[i].f) > 0 ) tmp = min(tmp,h[ edge[i].v ] );    }    if( --vh[ h[u] ] == 0 ) h[S] = N;    else ++vh[ h[u]=tmp+1 ];    return flow-sum;}double sap(){    double maxflow = 0;    memset(h,0,sizeof(h));    memset(vh,0,sizeof(vh));    vh[0] = N;    while( h[S] < N ) maxflow += dfs( S,inf );    return maxflow;}void DFS(int u){    vis[u] = true;    for(int i = head[u]; ~i; i = edge[i].nxt){        if( sign(edge[i].f) > 0 && !vis[ edge[i].v ] )            DFS( edge[i].v );    }}    void dfs(int u)    {        vis[u] = 1;        for(int i = head[u];i != -1;i = edge[i].nxt)        {          if( sign(edge[i].f) > 0 && !vis[ edge[i].v ] )            dfs( edge[i].v );        }    }    double build(double g)    {     memset( head, -1, sizeof(head));    idx = 0;        double all=0;        for(int i=1;i<=m;i++)        {            double temp=in[i].cost*1.0-g;            if( sign(temp) <0 )                all+=temp;            else            AddEdge(in[i].u,in[i].v,temp),AddEdge(in[i].v,in[i].u,temp);        }        return all;    }    bool judge(double mid)    {        double temp=build(mid);        double res=sap();        res+=temp;        if(res<eps) return true;        else return false;    }    void output(double ans)    {    int a[maxn];    memset(inde,false,sizeof(inde));   memset( head, -1, sizeof(head));    idx = 0;        for(int i=1;i<=m;i++)        {            double temp=in[i].cost*1.0-ans;            if( sign(temp) <0 )                inde[i]=true;             else  AddEdge(in[i].u,in[i].v,temp),AddEdge(in[i].v,in[i].u,temp);        }    memset(vis,0,sizeof(vis));    sap();    dfs(1);    int counter=0;    for(int i=1;i<=m;i++)    {        int tempa=in[i].u;        int tempb=in[i].v;        if((vis[tempa]&&!vis[tempb])||(!vis[tempa]&&vis[tempb]))            inde[i]=true;    }    for(int i=1;i<=m;i++)        if(inde[i])        a[++counter]=i;    printf("%d\n",counter);    for(int i=1;i<counter;i++)        printf("%d ",a[i]);    printf("%d\n\n",a[counter]);    }    int main()    {        while(scanf("%d%d",&n,&m)!=EOF)        {           S=1;T=n;N=n;            int ma=0;            for(int i=1;i<=m;i++)            {                scanf("%d%d%d",&in[i].u,&in[i].v,&in[i].cost);                if(in[i].cost>ma) ma=in[i].cost;            }            double left=0;            double right=ma*1.0;            while(right-left>eps)            {                double mid=(left+right)*0.5;                if(judge(mid))                    right=mid;                else left=mid;            }            output(left);        }    }

0 0
原创粉丝点击