[ABC214H]Collecting

Posted Tan_tan_tann

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[ABC214H]Collecting相关的知识,希望对你有一定的参考价值。

Collecting

题解

网络流板子。

首先题目已经暗示得非常明显了,我们可以考虑按原图的方法将图建出来,跑费用流。
对于原图中的边 ( u , v ) (u,v) (u,v),我们就连接 o u t u → i n v out_{u}\\rightarrow in_{v} outuinv,费用为 0 0 0流量为 k k k
而对于点的权值我们就相当于第一次到达这个点,所以在 i n u → i n v in_{u}\\rightarrow in_{v} inuinv上连接费用为 − v a l u -val_{u} valu,流量为 1 1 1,与费用为 0 0 0流量为 k k k的两条边。

但由于可能会产生负环,所以我们要先将原图缩点,得到一个 D A G DAG DAG,因为很明显,如果我们能够到达一个一个联通块中的某个点,那么我们一定可以到达这个联通块内的其他点,可以将权值都加在一个点上。
但之后仍存在负边,有可能会产生问题,我们考虑将所有路径都变成正的,对于每一条路径都加上 ∑ i = 1 n v a l i \\sum_{i=1}^{n}val_{i} i=1nvali
对于 o u t u → i n v out_{u}\\rightarrow in_{v} outuinv,我们的边权变为 s u m v − 1 − s u m u sum_{v-1}-sum_{u} sumv1sumu
i n u → o u t u in_{u}\\rightarrow out_{u} inuoutu的两条边边权变为 0 0 0 v a l u val_{u} valu
最后在 o u t u → t out_{u}\\rightarrow t outut的边上加上后缀 s u m n − s u m u sum_{n}-sum_{u} sumnsumu
这样保证我们走过整条路径时只有选择了的 v a l val val没有加上去,最后用 k ⋅ s u m n k\\cdot sum_{n} ksumn相减即可得到答案。

时间复杂度 O ( k n l o g   n ) O\\left(knlog\\,n\\right) O(knlogn),但事实上你必须将连通块的编号反过来才能过,否则会 T T T这太离谱了

源码

#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
#define MAXN 400005
#define lowbit(x) (x&-x)
#define reg register
#define pb push_back
#define mkpr make_pair
#define fir first
#define sec second
#define lson (rt<<1)
#define rson (rt<<1|1)
typedef long long LL;
typedef unsigned long long uLL;
const LL INF=1000000000000000000LL;
const int mo=1e9+7;
const int inv2=499122177;
const int jzm=2333;
const int lim=400000;
const int orG=3,invG=332748118;
const double Pi=acos(-1.0);
const double eps=1e-7;
typedef pair<int,int> pii;
template<typename _T>
_T Fabs(_T x){return x<0?-x:x;}
template<typename _T>
void read(_T &x){
	_T f=1;x=0;char s=getchar();
	while(s>'9'||s<'0'){if(s=='-')f=-1;s=getchar();}
	while('0'<=s&&s<='9'){x=(x<<3)+(x<<1)+(s^48);s=getchar();}
	x*=f;
}
template<typename _T>
void print(_T x){if(x<0){x=(~x)+1;putchar('-');}if(x>9)print(x/10);putchar(x%10+'0');}
LL gcd(LL a,LL b){return !b?a:gcd(b,a%b);}
int add(int x,int y,int p){return x+y<p?x+y:x+y-p;}
void Add(int &x,int y,int p){x=add(x,y,p);}
int qkpow(int a,int s,int p){int t=1;while(s){if(s&1LL)t=1ll*a*t%p;a=1ll*a*a%p;s>>=1LL;}return t;}
int n,m,K,tot,head[MAXN],val[MAXN],s,t,pre[MAXN],pw[MAXN];
int dfn[MAXN],low[MAXN],idx,belong[MAXN],cnt,sta[MAXN],stak;
LL dis[MAXN],sum[MAXN],sumval[MAXN];bool insta[MAXN];
vector<int>G[MAXN];
struct edge{int to,nxt;LL paid;int flow,op;}e[MAXN*10];
void addEdge(int u,int v,LL w,int f){e[++tot]=(edge){v,head[u],w,f};head[u]=tot;}
void addedge(int u,int v,LL w,int f){addEdge(u,v,w,f);e[tot].op=tot+1;addEdge(v,u,-w,0);e[tot].op=tot-1;}
struct ming{
	LL val;int id;
	bool operator < (const ming &rhs)const{return val>rhs.val;}
};
priority_queue<ming>q;
LL sakura(){
	LL res=0;
	while(1){
		for(int i=1;i<=cnt+cnt+2;i++)dis[i]=INF;
		while(!q.empty())q.pop();q.push((ming){0,s});dis[s]=0;
		while(!q.empty()){
			ming tt=q.top();int u=tt.id;q.pop();if(tt.val>dis[u])continue;
			for(int i=head[u];i;i=e[i].nxt){
				int v=e[i].to;LL w=e[i].paid;
				if(dis[v]>dis[u]+w&&e[i].flow>0){
					dis[v]=dis[u]+w;pre[v]=u;pw[v]=i;
					q.push((ming){dis[v],v});
				}
			}
		}
		if(dis[t]>INF-1)break;int minn=10;
		for(int i=t;i^s;i=pre[i])minn=min(minn,e[pw[i]].flow);res+=1ll*minn*dis[t];
		for(int i=t;i^s;i=pre[i])e[pw[i]].flow-=minn,e[e[pw[i]].op].flow+=minn;
	}
	return res;
}
void tarjan(int x){
	dfn[x]=low[x]=++idx;sta[++stak]=x;insta[x]=1;
	int siz=G[x].size();
	for(int i=0;i<siz;i++){
		int v=G[x][i];
		if(!dfn[v])tarjan(v),low[x]=min(low[x],low[v]);
		else if(insta[v])low[x]=min(low以上是关于[ABC214H]Collecting的主要内容,如果未能解决你的问题,请参考以下文章

「专题训练」Collecting Bugs(POJ-2096)

python+spark程序代码片段

Collecting package metadata (current_repodata.json): failed

Collecting Bugs(概率dp)

POJ2096Collecting Bugs

poj2096Collecting Bugs