zoukankan      html  css  js  c++  java
  • bzoj3876: [Ahoi2014&Jsoi2014]支线剧情

    题意:给一幅图,从1开始,每条边有边权最少走一遍,可以在任意点退出,问最小花费
    题解:上下界费用流,每个边都流一遍,然后为了保证流量平衡,新建源点汇点,跑费用流把流量平衡

    /**************************************************************
        Problem: 3876
        User: walfy
        Language: C++
        Result: Accepted
        Time:140 ms
        Memory:2868 kb
    ****************************************************************/
     
    //#pragma GCC optimize(2)
    //#pragma GCC optimize(3)
    //#pragma GCC optimize(4)
    //#pragma GCC optimize("unroll-loops")
    //#pragma comment(linker, "/stack:200000000")
    //#pragma GCC optimize("Ofast,no-stack-protector")
    //#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
    #include<bits/stdc++.h>
    #define fi first
    #define se second
    #define db double
    #define mp make_pair
    #define pb push_back
    #define pi acos(-1.0)
    #define ll long long
    #define vi vector<int>
    #define mod 1000000009
    #define ld long double
    //#define C 0.5772156649
    #define ls l,m,rt<<1
    #define rs m+1,r,rt<<1|1
    #define pll pair<ll,ll>
    #define pil pair<int,ll>
    #define pli pair<ll,int>
    #define pii pair<int,int>
    #define ull unsigned long long
    //#define base 1000000000000000000
    #define fin freopen("a.txt","r",stdin)
    #define fout freopen("a.txt","w",stdout)
    #define fio ios::sync_with_stdio(false);cin.tie(0)
    inline ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
    inline void sub(ll &a,ll b){a-=b;if(a<0)a+=mod;}
    inline void add(ll &a,ll b){a+=b;if(a>=mod)a-=mod;}
    template<typename T>inline T const& MAX(T const &a,T const &b){return a>b?a:b;}
    template<typename T>inline T const& MIN(T const &a,T const &b){return a<b?a:b;}
    inline ll qp(ll a,ll b){ll ans=1;while(b){if(b&1)ans=ans*a%mod;a=a*a%mod,b>>=1;}return ans;}
    inline ll qp(ll a,ll b,ll c){ll ans=1;while(b){if(b&1)ans=ans*a%c;a=a*a%c,b>>=1;}return ans;}
     
    using namespace std;
     
    const ull ba=233;
    const db eps=1e-5;
    const ll INF=0x3f3f3f3f3f3f3f3f;
    const int N=500+10,maxn=100000+10,inf=0x3f3f3f3f;
     
    bool vis[N];
    int cnt,head[N],pre[N],path[N],dis[N],in[N],out[N];
    struct edge{int to,Next,c,cost;}e[maxn];
    void init(){memset(head,-1,sizeof head);cnt=0;}
    void add(int u,int v,int c,int cost)
    {
    //    printf("%d %d %d %lld
    ",u,v,c,cost);
        e[cnt].to=v;e[cnt].c=c;e[cnt].cost=cost;e[cnt].Next=head[u];head[u]=cnt++;
        e[cnt].to=u;e[cnt].c=0;e[cnt].cost=-cost;e[cnt].Next=head[v];head[v]=cnt++;
    }
    bool spfa(int s,int t)
    {
        memset(pre,-1,sizeof pre);
        memset(dis,inf,sizeof dis);
        memset(vis,0,sizeof vis);
        dis[s]=0;vis[s]=1;
        queue<int>q;q.push(s);
        while(!q.empty())
        {
            int x=q.front();q.pop();
            vis[x]=0;
            for(int i=head[x];~i;i=e[i].Next)
            {
                int te=e[i].to;
                if(e[i].c>0&&dis[x]+e[i].cost<dis[te])
                {
                    dis[te]=dis[x]+e[i].cost;
                    pre[te]=x;path[te]=i;
                    if(!vis[te])q.push(te),vis[te]=1;
                }
            }
        }
        return pre[t]!=-1;
    }
    int mincostmaxflow(int s,int t)
    {
        int cost=0,flow=0;
        while(spfa(s,t))
        {
            int f=inf;
            for(int i=t;i!=s;i=pre[i])
                if(e[path[i]].c<f)
                   f=e[path[i]].c;
            flow+=f;cost+=dis[t]*f;
            for(int i=t;i!=s;i=pre[i])
            {
                e[path[i]].c-=f;
                e[path[i]^1].c+=f;
            }
        }
        return cost;
    }
    int main()
    {
        init();
        int n,tot=0;scanf("%d",&n);
        int s=1,t=n+1,ss=n+2,tt=n+3,ans=0;
        for(int i=1,k;i<=n;i++)
        {
            for(scanf("%d",&k);k;k--)
            {
                int a,b;scanf("%d%d",&a,&b);
                add(i,a,5000,b);
                out[i]++,in[a]++;ans+=b;
            }
            add(i,t,5000,0);
        }
        add(t,s,5000,0);
        for(int i=1;i<=n;i++)
        {
            if(in[i]>out[i])add(ss,i,in[i]-out[i],0);
            else add(i,tt,out[i]-in[i],0);
        }
        ans+=mincostmaxflow(ss,tt);
        printf("%d
    ",ans);
        return 0;
    }
    /********************
    6
    2 2 1 3 2
    2 4 3 5 4
    2 5 5 6 6
    0
    0
    0
    ********************/
    
  • 相关阅读:
    微信 token ticket jsapi_ticket access_token 获取 getAccessToken get_jsapi_ticket方法
    PHP 日志 记录 函数 支持 数组 对象 新浪 sae 环境 去掉 空格 换行 格式化 输出 数组转字符串
    原生 原始 PHP连接MySQL 代码 参考mysqli pdo
    PHP 数字金额转换成中文大写金额的函数 数字转中文
    使用PHPMailer发送带附件并支持HTML内容的邮件
    设置输出编码格式 header 重定向 执行时间 set_time_limit 错误 报告 级别 error_reporting
    html5 bootstrap pannel table 协议 公告 声明 文书 模板
    指向指针的指针
    二级指针
    c语言:当指针成为参数后
  • 原文地址:https://www.cnblogs.com/acjiumeng/p/10484272.html
Copyright © 2011-2022 走看看