码迷,mamicode.com
首页 > 其他好文 > 详细

题解 CF863F 【Almost Permutation】

时间:2020-08-17 17:20:47      阅读:72      评论:0      收藏:0      [点我收藏+]

标签:i++   cos   efi   cin   define   cdn   log   CMF   最大流   

本弱鸡的第一道黑题!

发篇题解纪念一下!

这道题目我们可以用最小费用最大流来解决。
首先,你要会打费用流的模板。
不会的可以参考这里
然后我们开始推式子...
\(U_i\)表示第\(i\)个数\(\ge U_i\)
\(D_i\)表示第\(i\)个数\(\ge D_i\)
我们先将源点\(Start\)向第一层流量为\(\mathcal{1}\)费用为\(0\)
然后跑一边费用流就好了呀!
不会费用流的去这里
我的代码跑的还不错,Rank2

#include<bits/stdc++.h>
#define MAX 201
using namespace std;
int TotalPoint,TotalEdge;
int Start,End,Sp;
int Ans,AllCost;
bool Visit[MAX];
bool VisitDfs[MAX];
int Dist[MAX];
int U[MAX],D[MAX];
vector<int>Edge[MAX];
vector<int>Stream[MAX];
vector<int>Cost[MAX];
vector<int>Size[MAX];
inline void AddEdge(int From,int To,int NowStream,int NowCost)
{
    Edge[From].push_back(To);
    Edge[To].push_back(From);
    Stream[From].push_back(NowStream);
    Stream[To].push_back(0);
    Cost[From].push_back(NowCost);
    Cost[To].push_back(-NowCost);
    Size[From].push_back(Edge[To].size()-1);
    Size[To].push_back(Edge[From].size()-1);
}
inline bool Spfa(int Start,int End)
{
    register queue<int>Queue;
    register int i;
    for(i=1;i<=Sp;i++)
    {
        VisitDfs[i]=false;
        Visit[i]=false;
        Dist[i]=2147483647;
    }
    Visit[Start]=true;
    Dist[Start]=0;
    Queue.push(Start);
    while(!Queue.empty())
    {
        register int Top;
        Top=Queue.front();
        Queue.pop();
        Visit[Top]=false;
        for(i=0;i<Edge[Top].size();i++)
        {
            register int Next;
            Next=Edge[Top][i];
            if(Dist[Top]+Cost[Top][i]<Dist[Next]&&Stream[Top][i])
            {
                Dist[Next]=Dist[Top]+Cost[Top][i];
                if(!Visit[Next])
                {
                    Visit[Next]=true;
                    Queue.push(Next);
                }
            }
        }
    }
    return Dist[End]!=2147483647;
}
inline int Dfs(int Now,int End,int Min)
{
    if(!Min||Now==End)
    {
        return Min;
    }
    register int Return;
    Return=0;
    VisitDfs[Now]=1;
    register int i;
    for(i=0;i<Edge[Now].size();i++)
    {
        register int Next=Edge[Now][i];
        if(Dist[Now]+Cost[Now][i]==Dist[Next]&&Stream[Now][i]&&!VisitDfs[Next])
        {
            register int MinStream;
            MinStream=Dfs(Next,End,min(Min,Stream[Now][i]));
            Stream[Now][i]-=MinStream;
            Stream[Next][Size[Now][i]]+=MinStream;
            Min-=MinStream;
            Return+=MinStream;
            AllCost+=MinStream*Cost[Now][i];
        }
    }
    return Return;
}
inline void Mcmf()
{
    while(Spfa(Start,End))
    {
        Ans=Ans+Dfs(Start,End,2147483647);
    }
}
int main(void)
{
    register int i,j;
    cin>>TotalPoint>>TotalEdge;
    Start=TotalPoint*2+1;
    End=TotalPoint*2+2;
    Sp=TotalPoint*2+2;
    for(i=1;i<=TotalPoint;i++)
    {
    	U[i]=1;
    	D[i]=TotalPoint;
	}
    for(i=1;i<=TotalEdge;i++)
    {
        register int Left,Right,Opt,Value;
        cin>>Opt>>Left>>Right>>Value;
        for(j=Left;j<=Right;j++)
        {
        	if(Opt==1)
        	{
        		U[j]=max(U[j],Value);
			}
			else
			{
				D[j]=min(D[j],Value);
			}
		}
    }
    for(i=1;i<=TotalPoint;i++)
    {
    	AddEdge(Start,i,1,0);
	}
	for(i=1;i<=TotalPoint;i++)
	{
		for(j=U[i];j<=D[i];j++)
		{
			AddEdge(i,j+TotalPoint,1,0);
		}
	}
	for(i=1;i<=TotalPoint;i++)
	{
		for(j=1;j<=TotalPoint;j++)
		{
			AddEdge(i+TotalPoint,End,1,2*j-1);
		}
	}
    Mcmf();
    if(Ans==TotalPoint)
    {
    	cout<<AllCost<<endl;
	}
	else
	{
		cout<<-1<<endl;
	}
    return 0;
}

题解 CF863F 【Almost Permutation】

标签:i++   cos   efi   cin   define   cdn   log   CMF   最大流   

原文地址:https://www.cnblogs.com/Xsmyy/p/13504255.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!