zoukankan      html  css  js  c++  java
  • 洛咕 P2494 [SDOI2011]保密

    出题人没素质啊,强行拼题还把题面写得又臭又长。

    简单题面就是有一张图,每条边有两个权值(t,s),有无限支军队,一支军队可以打一个点,代价是从n到这个点的路径的(frac{sum t}{sum s})

    有m条限制,每条限制就是a,b两个点至少选一个,求最小代价。

    首先第一部分也就是要求每个点的代价,显然分数规划,随便做做就没了。

    第二部分就是裸的最小割,随便做做就没了。

    #include<bits/stdc++.h>
    #define il inline
    #define vd void
    typedef long long ll;
    il int gi(){
        int x=0,f=1;
        char ch=getchar();
        while(!isdigit(ch)){
            if(ch=='-')f=-1;
            ch=getchar();
        }
        while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
        return x*f;
    }
    #define maxn 710
    int n,m;
    struct edge{int d,t,s;};
    std::vector<edge>G[maxn];
    double W[maxn],dist[maxn];int s[maxn],_s[maxn];
    il vd SPFA(double Mid){
        static bool inq[maxn];
        static int que[maxn],hd,tl;
        for(int i=1;i<=n;++i)dist[i]=1e9;
        hd=tl=0;que[tl++]=n;dist[n]=0;
        while(hd^tl){
            int x=que[hd];
            for(int i=0;i<G[x].size();++i)
                if(dist[G[x][i].d]>dist[x]+G[x][i].t-Mid*G[x][i].s){
                    dist[G[x][i].d]=dist[x]+G[x][i].t-Mid*G[x][i].s;
                    if(!inq[G[x][i].d])inq[G[x][i].d]=1,que[tl++]=G[x][i].d,tl%=maxn;
                }
            inq[x]=0;++hd;hd%=maxn;
        }
    }
    il vd solve(int l,int r,double L,double R){
        if(R-L<1e-3){
            L=(L+R)*0.5;
            for(int i=l;i<=r;++i)W[s[i]]=L;
            return;
        }
        if(l>r)return;
        double Mid=(L+R)*0.5;
        SPFA(Mid);
        int _l=l-1,_r=r+1;
        for(int i=l;i<=r;++i)
            if(dist[s[i]]<0)_s[++_l]=s[i];
            else _s[--_r]=s[i];
        memcpy(s+l,_s+l,4*(r-l+1));
        solve(l,_l,L,Mid);
        solve(_r,r,Mid,R);
    }
    #define maxm 100000
    int fir[maxn],head[maxn],dep[maxn],dis[maxm],nxt[maxm],id=1,S=maxn-1,T=maxn-2;double w[maxm];
    il vd link(int a,int b,double c){
        nxt[++id]=fir[a],fir[a]=id,dis[id]=b,w[id]=c;
        nxt[++id]=fir[b],fir[b]=id,dis[id]=a,w[id]=0;
    }
    il bool BFS(){
        static int que[maxn],hd,tl;
        hd=tl=0;que[tl++]=S;
        memset(dep,0,sizeof dep);dep[S]=1;
        while(hd^tl){
            int x=que[hd++];
            for(int i=fir[x];i;i=nxt[i])
                if(w[i]>1e-5&&!dep[dis[i]])
                    dep[dis[i]]=dep[x]+1,que[tl++]=dis[i];
        }
        return dep[T];
    }
    il double Dinic(int x,double maxflow){
        if(x==T)return maxflow;
        double ret=0;
        for(int i=fir[x];i;i=nxt[i])
            if(w[i]>1e-5&&dep[dis[i]]==dep[x]+1){
                double d=Dinic(dis[i],std::min(w[i],maxflow-ret));
                w[i]-=d,w[i^1]+=d,ret+=d;
                if(maxflow-ret<1e-6)break;
            }
        return ret;
    }
    int main(){
    #ifndef ONLINE_JUDGE
        freopen("2494.in","r",stdin);
        freopen("2494.out","w",stdout);
    #endif
        n=gi(),m=gi();
        int a,b,_t,_s;
        while(m--)a=gi(),b=gi(),_t=gi(),_s=gi(),G[a].push_back((edge){b,_t,_s});
        for(int i=1;i<n;++i)s[i]=i;
        solve(1,n-1,0,7777);
        for(int i=1;i<=n;++i)if(W[i]>7776)W[i]=1e9;
        int m1=gi(),n1=gi();
        for(int i=1;i<=n1;i+=2)link(S,i,W[i]);
        for(int i=2;i<=n1;i+=2)link(i,T,W[i]);
        while(m1--)a=gi(),b=gi(),link(a,b,1e9);
        double ans=0;while(BFS())memcpy(head,fir,sizeof fir),ans+=Dinic(S,1e9);
        if(ans>9e8)puts("-1");
        else printf("%.1lf
    ",ans);
        return 0;
    }
    
  • 相关阅读:
    b_lc_第k个排列(暴搜 / 数学剪枝)
    sql语句大全(2)
    经典SQL语句大全
    存储过程格式
    经典SQL语句大全(实例)非常不错的和excel等文档实例结合的sql
    触发器MSSQL常用操作
    最好的C#学习网站
    C# 反射入门知识
    MSSQL经典语句
    一些很酷的.Net技巧
  • 原文地址:https://www.cnblogs.com/xzz_233/p/9973584.html
Copyright © 2011-2022 走看看