首页 > 代码库 > 暑假集训day3

暑假集训day3

今天主要讲的是网络流

涉及到一下2题

Dual Core CPU   和   利润

Dual Core CPU 题目见poj 3469

用最大流做即可

建图很简单不说了

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector> 
#include<queue>
using namespace std;
inline int read(){
    int t=1,num=0;
    char c=getchar();
    while(c>9||c<0){if(c==-)t=-1;c=getchar();}
    while(c>=0&&c<=9){num=num*10+c-0;c=getchar();}
    return num*t;
}
const int INF=10000010;
struct edge{
    int to;int c;int rev;
};
vector<edge> g[20101];
int n,m,iter[20101],level[20101];
void add(int f,int t,int c){
    g[f].push_back((edge){t,c,g[t].size()});
    g[t].push_back((edge){f,0,g[f].size()-1});
}
void bfs(int s){
    memset(level,0,sizeof(level));
    queue<int>q;
    level[s]=1;
    q.push(s);
    while(!q.empty()){
        int v=q.front();q.pop();
        for(int i=0;i<g[v].size();i++){
            edge &e=g[v][i];
            if(e.c>0&&level[e.to]==0){
                level[e.to]=level[v]+1;
                q.push(e.to);
            }
        }
    }
}
int dfs(int v,int t,int f){
    if(v==t) return f;
    for(int &i=iter[v];i<g[v].size();i++){
        edge &e=g[v][i];
        if(e.c>0&&level[v]+1==level[e.to]){
            int d=dfs(e.to,t,min(f,e.c));
            if(d>0){
                e.c-=d;
                g[e.to][e.rev].c+=d;
                return d;
            }
        }
    }
    return 0;
}
int flow(int s,int t){
    int flow=0;
    while(1){
        bfs(s);
        if(level[t]==0) return flow;
        memset(iter,0,sizeof(iter));
        int f;
        while((f=dfs(s,t,INF))>0)flow+=f;
    }
}
int main()
{
    n=read();m=read();
    for(int i=1;i<=n;i++){
        int a,b;a=read();b=read();
        add(0,i,b);add(i,n+1,a);
    }
    for(int i=1;i<=m;i++){
        int x,y,w;x=read();y=read();w=read();
        add(x,y,w);add(y,x,w);
    }
    printf("%d",flow(0,n+1));
    return 0;
}

利润 题目见9018 1400

本题比较难。。要因为涉及乘法。要把乘法改成加法做最小费用最大流。

调用到cmath库中的exp和log

但是由于exp和log的误差较大,可能在运行的过程中使得某些值为导致死循环

因此需要调节精度

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
int h[1510],used[1510],que[100010],last[1510];
int k=1,ans1=0;double ans2=0;int n,m,s;
double INF=0x7fffff,d[1510];
const double eps=1e-8;//调节精度,见33行 
inline int read(){
    int t=1,num=0;char c=getchar();
    while(c>9||c<0){if(c==-)t=-1;c=getchar();}
    while(c>=0&&c<=9){num=(num<<3)+(num<<1)+c-0;c=getchar();}
    return num*t;
}
struct edge{
    int to;int cap;double cost;int next;
}g[40010];
inline void add(int f,int t,int c1,double c2){
    g[++k].next=h[f];h[f]=k;g[k].to=t;g[k].cap=c1;g[k].cost=c2;
    g[++k].next=h[t];h[t]=k;g[k].to=f;g[k].cap=0;g[k].cost=-c2;
}
bool spfa(int s,int t){
    memset(last,0,sizeof(last));
    for(int i=1;i<=n;i++)d[i]=INF;
    memset(used,0,sizeof(used));
    int tail,head;
    head=tail=50002;
    que[head]=s;used[s]=1;d[s]=0;
    while(head>=tail){
        int x=que[tail++];
        for(int i=h[x];i;i=g[i].next){
            if(g[i].cap&&d[x]+g[i].cost+eps<d[g[i].to]){
                d[g[i].to]=d[x]+g[i].cost;
                last[g[i].to]=i;
                if(!used[g[i].to]){
                    if(d[g[i].to]<d[que[tail]])que[--tail]=g[i].to;
                    else que[++head]=g[i].to;
                    used[g[i].to]=1;
                }
            }
        }
        used[x]=0;
    }
    return d[t]!=INF;
}
void mcf(int t){
    int minn=0x7fffffff;double cnt=0;
    for(int i=last[t];i;i=last[g[i^1].to])minn=min(minn,g[i].cap);
    ans1+=minn;
    for(int i=last[t];i;i=last[g[i^1].to]){
        cnt+=g[i].cost;
        g[i].cap-=minn;
        g[i^1].cap+=minn;
    }
    ans2+=s*exp(cnt)*minn;
}
int main()
{
    n=read();m=read();s=read();
    for(int i=1;i<=m;i++){
        int u,v,c,x;u=read();v=read();c=read();x=read();
        add(u,v,c,log(1.0+x/100.0));
    }
    while(spfa(1,n))mcf(n);
    printf("%d\n%.1lf",ans1,ans2);
    return 0;
}

本文由Yzyet编写,网址为www.cnblogs.com/Yzyet。非Yzyet同意,禁止转载,侵权者必究。

暑假集训day3