1. 程式人生 > >洛咕 P2494 [SDOI2011]保密

洛咕 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\n",ans);
    return 0;
}