《网 络 瘤:从入门到入土》第二卷

\[\huge\color{cornflowerblue}{\texttt{Net flow studying notes: NO.2.}} \]

\[\large\color{gold}{\texttt{Only Problems Here.}} \]



\(\tt{P4542}\) 营救皮卡丘

\[\huge\color{darkcyan}{\texttt{1.锂性分析}} \]

  • 对于经过的点必须按顺序出现(即在经过1~K-1前不能经过K):
    我们可以按顺序将点拆分成入点和出点,图中的边即为输入中的入点连向另一端的出点.入点连源点,出点连汇点.
    \(\tt{floyd}\)跑一遍全源最短路,两点间边权即为最短路.
    注意编号为0的点与源点的边容量为k.

\[\huge\color{darkcyan}{\texttt{2.感性开打}} \]

#include <bits/stdc++.h>
#define ri register int
#define MAXN 200001
using namespace std;
const int inf=0x3f3f3f3f;

int n,m,k,s,t,cntr;
int cst,mfl;
int head[MAXN];
int cur[MAXN];
int dist[MAXN];
int gra[2001][2001];
int q[MAXN];
bool vis[MAXN];

inline void floyd()
{
	for(ri k=1;k<=n;k++)
	for(ri i=1;i<=n;i++)
	for(ri j=1;j<=n;j++)
	if(k<i||k<j)//注意必须有限制,疯狂WA10次
	gra[i][j]=min(gra[i][j],gra[i][k]+gra[k][j]);
}

struct edge{
	int to,next,flow,cost;
}e[MAXN];

inline void add(int u,int v,int w,int c)
{
	e[cntr].to=v;
	e[cntr].flow=w;
	e[cntr].cost=c;
	e[cntr].next=head[u];
	head[u]=cntr++;
}

inline void orz(int u,int v,int w,int c)
{
	add(u,v,w,c);
	add(v,u,0,-c);
}

inline bool SPFA()
{
	memset(dist,inf,sizeof(dist));
	memcpy(cur,head,sizeof(head));
	dist[s]=0;
	vis[s]=1;
	int l=0,r=1;
	q[++l]=s;
	while(l<=r)
	{
		int u=q[l++];
		vis[u]=0;
		for(ri i=head[u];~i;i=e[i].next)
		{
			int v=e[i].to,c=e[i].cost;
			if(dist[v]>dist[u]+c&&e[i].flow)
			{
				dist[v]=dist[u]+c;
				if(!vis[v])
				vis[v]=1,q[++r]=v;
			}
		}
	}
	return dist[t]!=inf;
}

inline int dfs(int now,int maxfl)
{
	if(now==t||maxfl==0)
	return maxfl;
	vis[now]=1;
	int tflow=0;
	for(ri i=cur[now];~i&&tflow<maxfl;i=e[i].next)
	{
		cur[now]=i;
		int v=e[i].to,c=e[i].cost;
		if(!vis[v]&&dist[v]==dist[now]+c&&e[i].flow)
		{
			int cf=dfs(v,min(maxfl-tflow,e[i].flow));
			if(cf)
			{
				cst+=cf*c;
				e[i].flow-=cf;
				e[i^1].flow+=cf;
				tflow+=cf; 
			}
		}
	}
	vis[now]=0;
	return tflow;
}

inline void SSP()
{
	int ad=0;
	while(SPFA())
		while(ad=dfs(s,inf));
	printf("%d",cst);
}

inline int r()
{
	int fed=0;
	char in=getchar();
	bool flag=1;
	while(!isdigit(in))
	flag&=(in!='-'),in=getchar();
	while(isdigit(in))
	fed=fed*10+in-'0',in=getchar();
	return (2*flag-1)*fed;
}

int main()
{
	memset(head,-1,sizeof(head));
	n=r(),m=r();
	n++;
	for(ri i=1;i<=n;i++)
	for(ri j=1;j<=n;j++)
	{
		if(i==j)
		continue;
		gra[i][j]=inf;
	}
	k=r();
	s=(n<<1)+1,t=(n<<1)+2;
	for(ri i=1;i<=m;i++)
	{
		int a,b,l;
		a=r(),b=r();
		a++,b++;
		l=r();
		gra[a][b]=gra[b][a]=min(gra[a][b],l);
	}
	floyd();
	orz(s,1,k,0);
	orz(1+t,t,1,0);
	for(ri i=2;i<=n;i++)
	orz(s,i,1,0),orz(i+t,t,1,0);
	for(ri i=1;i<=n;i++)
	for(ri j=i+1;j<=n;j++)
	if(gra[i][j]!=inf)
	orz(i,j+t,inf,gra[i][j]);
	SSP();
	return 0;
}

\[\texttt{to be continued......} \]


\[\color{skyblue}{\texttt{And We,}} \]

\[\color{skyblue}{\texttt{We Burn Faster Than Lights,}} \]

\[\color{skyblue}{\texttt{Shine Across In The Night Sky,}} \]

\[\color{skyblue}{\texttt{We Burn Faster Than Lights.}} \]

\[\color{gold}{◢_◤} \]

posted @ 2021-11-07 18:07  Neutral1sed  阅读(46)  评论(0)    收藏  举报