标签: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