Gym 100204G Network Wars(最小割+0/1分数规划)

来源:互联网 发布:java 中编译后无src 编辑:程序博客网 时间:2024/04/29 12:37
题目地址:http://codeforces.com/gym/100204/attachments

思路:

1.即要求求:


其中Xi=1代表选择该条边,为0代表不选择该边。

2.转化为:


即:



二分ans,设置所有边为W-ans,若一条边小于0,则直接将其加入(该边小于平均值,加入则会使最终结果更小),设所有负权边和为sum。求最小割,判断最小割+sum是否小于0,即可。(若小于等于0,则在ans在[l,mid]内,否则ans在[mid,r]内)

3.输出答案时,dfs染色,从起点S开始,只经过flow<cap的边,标记经过的点(vis[u]=1)。若对于边(u,v),vis[u]+vis[v]=1,则该边为割边,将其输出,同时将所有负权边输出。

#include<cmath>#include<queue>#include<cstdio>#include<vector>#include<cstring>#include<iostream>#include<algorithm>#define S 1#define T n#define debugusing namespace std;const double eps=1e-6;const int maxn=100+50;const int maxm=800+50;const int INF=0x3f3f3f3f;struct Edge{    int from, to;    double cap, flow;    Edge(int a,int b,double c,double d):from(a),to(b),cap(c),flow(d) {}};int dcmp(double x){    if(fabs(x)<eps) return 0;    else return x<0?-1:1;}struct Dinic{    int n, m, s, t;    vector<Edge> edges;    vector<int> G[maxn];    bool vis[maxn];    int d[maxn];    int cur[maxn];    void init(int n)    {        this->n=n;        for(int i = 0; i <= n; i++) G[i].clear();        edges.clear();    }    void addEdge(int from, int to, double cap)    {        edges.push_back(Edge(from,to,cap,0));        edges.push_back(Edge(to,from,0,0));        m = edges.size();        G[from].push_back(m-2);        G[to].push_back(m-1);    }    bool BFS()    {        memset(vis, 0, sizeof(vis));        queue<int> Q;        Q.push(s);        vis[s] = 1;        d[s] = 0;        while(!Q.empty())        {            int x = Q.front();            Q.pop();            for(int i = 0; i < G[x].size(); i++)            {                Edge& e = edges[G[x][i]];                if(!vis[e.to] && dcmp(e.cap - e.flow)>0)                {                    vis[e.to] = 1;                    d[e.to] = d[x] + 1;                    Q.push(e.to);                }            }        }        return vis[t];    }    double DFS(int x, double a)    {        if(x == t || dcmp(a) == 0) return a;        double flow = 0, f;        for(int& i = cur[x]; i < G[x].size(); i++)        {            Edge& e = edges[G[x][i]];            if(d[x] + 1 == d[e.to] && (f = DFS(e.to, min(a, e.cap-e.flow))) > 0)            {                e.flow += f;                edges[G[x][i]^1].flow -= f;                flow += f;                a -= f;                if(dcmp(a) == 0) break;            }        }        return flow;    }    double MaxFlow(int s, int t)    {        this->s = s;        this->t = t;        double flow = 0;        while(BFS())        {            memset(cur, 0, sizeof(cur));            flow += DFS(s, INF);        }        return flow;    }};struct Node{    int u,v,w;};Dinic g;int n,m;int vis[maxn];int flag[maxn][maxn];Node e[maxm];double check(double x,int id){    g.init(n);    double sum=0.0;    for(int i=0; i<m; i++)    {       if(dcmp(e[i].w-x)>0)       {        g.addEdge(e[i].u,e[i].v,e[i].w-x);        g.addEdge(e[i].v,e[i].u,e[i].w-x);        }        //cout<<x<<" "<<e[i].u<<" "<<e[i].v<<" "<<e[i].w-x<<endl;        if(id&&dcmp(e[i].w-x)<0) flag[e[i].u][e[i].v]=flag[e[i].v][e[i].u]=1;        sum+=min(e[i].w-x,0.0);    }    //cout<<"***********"<<endl;    return sum+g.MaxFlow(S,T);}void dfs(int u){    vis[u]=1;    for(int i=0; i<g.G[u].size(); i++)    {        Edge& e=g.edges[g.G[u][i]];        if(!vis[e.to]&&dcmp(e.flow-e.cap)<0)        {            dfs(e.to);        }    }}void print(){    int tot=0;    vector<int> ans;    for(int i=0; i<m; i++)    {        if(flag[e[i].u][e[i].v]||vis[e[i].u]^vis[e[i].v])        {            tot++;            ans.push_back(i+1);        }    }    printf("%d\n",tot);    for(int i=0; i<ans.size(); i++)    {        if(i==0) printf("%d",ans[i]);        else printf(" %d",ans[i]);    }    printf("\n");}int main(){#ifdef debug    freopen("network.in","r",stdin);    freopen("network.out","w",stdout);#endif // debug    scanf("%d%d",&n,&m);    for(int i=0; i<m; i++)    {        scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);    }    double l=0.0,r=1e6,ans=0.0;    while(fabs(r-l)>eps)    {        double mid=(l+r)/2;        if(dcmp(check(mid,0))<=0)        {            r=mid;            ans=mid;            //cout<<ans<<" "<<check(mid)<<endl;        }        else        {            l=mid;        }    }    check(ans,1);    dfs(S);    print();    return 0;}



阅读全文
0 0
原创粉丝点击