zoukankan      html  css  js  c++  java
  • 2015-2016 ACM-ICPC, NEERC, Moscow Subregional Contest J

    题意:有n张照片,每张照片上有一些妹子,要按照片顺序给妹纸安排男朋友,如果妹纸i安排的男朋友之前有女朋友,那么费用+wi,求总费用最小,和输出路径
    题解:费用流,先把照片天数建点i连i+1,流量k(最多的男朋友数量),费用0,再把所有按照片顺序出现的妹纸拆点,自己流自己,流量1,费用-inf(保证要安排上),假设当前妹纸是第i天出现的,如果该妹纸之前出现过,我们连一条上一次的到当前点,流量为1,费用0(表示沿用上一次的男朋友),否则从第1个照片点连一条流量为1,费用0的边(表示安排一个之前没有用过的男朋友),还要从i连一条流量为1,费用wi的边(表示用上一天某个妹纸的男朋友),连一条到i+1流量为1,费用0的边(为了让下一天的妹纸能重复利用男朋友),输出路径时dfsk次表示经过的点都是安排了第i号朋友

    //#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 1000000007
    #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 cd complex<double>
    #define ull unsigned long long
    //#define base 1000000000000000000
    #define Max(a,b) ((a)>(b)?(a):(b))
    #define Min(a,b) ((a)<(b)?(a):(b))
    #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 double eps=1e-8;
    const ll INF=0x3f3f3f3f3f3f3f3f;
    const int N=20200+10,maxn=200000+10,inf=0x3f3f3f3f;
    
    struct edge{
        int from,to,Next,c;
        int cost;
    }e[maxn];
    int cnt,head[N],s,t,pre[N],path[N];
    ll dis[N];
    bool vis[N];
    void init(){memset(head,-1,sizeof head);cnt=0;}
    void add(int u,int v,int c,int cost)
    {
        e[cnt].from=u;e[cnt].to=v;e[cnt].c=c;e[cnt].cost=cost;e[cnt].Next=head[u];head[u]=cnt++;
        e[cnt].from=v;e[cnt].to=u;e[cnt].c=0;e[cnt].cost=-cost;e[cnt].Next=head[v];head[v]=cnt++;
    }
    bool spfa()
    {
        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;
    }
    ll mincostmaxflow()
    {
        ll cost=0,flow=0;
        while(spfa())
        {
            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 v[N],has[N],l[N],r[N],tot,ans[N];
    void dfs(int u,int p)
    {
        ans[u]=p;if(u==t)return ;
        for(int i=head[u];~i;i=e[i].Next)
        {
            if(i&1)continue;
            if(e[i^1].c==0)continue;
            e[i^1].c--,e[i].c++;
            dfs(e[i].to,p);
            return ;
        }
    }
    int main()
    {
        int n,m,k;
        scanf("%d%d%d",&n,&k,&m);
        init();s=0,t=n+1;
        for(int i=1;i<=n+1;i++)add(i-1,i,k,0);
        for(int i=1;i<=m;i++)scanf("%d",&v[i]);
        tot=n+1;ll sum=0;
        for(int x,y,i=1;i<=n;i++)
        {
            for(l[i]=tot+1,scanf("%d",&x);x;x--)
            {
                scanf("%d",&y);tot++;
                if(has[y])add(has[y],tot,1,0);
                else add(1,tot,1,0);
                add(i,tot,1,v[y]);add(tot,tot+1,1,-inf);add(tot+1,i+1,1,0);
                tot++;has[y]=tot;sum+=inf;
            }
            r[i]=tot;
        }
        printf("%lld
    ",mincostmaxflow()+sum);
        for(int i=1;i<=k;i++)dfs(0,i);
        for(int i=1;i<=n;i++)
        {
            for(int j=l[i];j<=r[i];j+=2)
                printf("%d ",ans[j]);
            puts("");
        }
        return 0;
    }
    /********************
    
    ********************/
    
  • 相关阅读:
    Kuangbin带你飞 专题二十 斜率DP
    牛客每日一题3月
    2020 SWJTU-ICPC Training Round #2(18年福建省赛)部分题解
    codeforces每日一题31-40
    SWJTU校队训练&Codeforces&Atcoder&&牛客三月补题
    Kuangbin带你飞-专题九连通图
    POJ 3667 Hotel(线段树区间合并)
    AtCoder Beginner Contest 157(题解)
    2.22专项测试复盘
    2.21专项测试复盘
  • 原文地址:https://www.cnblogs.com/acjiumeng/p/9991645.html
Copyright © 2011-2022 走看看