模拟赛 花园的守护之神(时间限制:1s;空间限制:256MB)

题目描述

看着正在被上古神兽们摧残的花园,花园的守护之神――小Bug同学泪流满面。然而,FZOI不相信眼泪,小bug与神兽们的战争将进行到底!
通过google,小Bug得知,神兽们来自遥远的戈壁。为了扭转战局,小Bug决定拖延神兽增援的速度。从戈壁到达花园的路径错综复杂,由若干段双向的小路组成。神兽们通过每段小路都需要一段时间。小Bug可以通过向其中的一些小路投掷小xie来拖延神兽。她可以向任意小路投掷小Xie,而且可以在同一段小路上投掷多只小xie。每只小Xie可以拖延神兽一个单位的时间。即神兽通过整段路程的总时间,等于没有小xie时他们通过同样路径的时间加上路上经过的所有小路上的小xie数目总和。
神兽们是很聪明的。他们会在出发前侦查到每一段小路上的小Xie数目,然后选择总时间最短的路径。小Bug现在很想知道最少需要多少只小Xie,才能使得神兽从戈壁来到花园的时间变长。作为花园中可爱的花朵,你能帮助她吗?

输入格式

第1行包括一个整数N,表示地图中路点的个数;一个整数M,表示小路个数;以及整数S和T,分别表示戈壁和花园的路点编号。N个路点分别被编号为自然数1~N。
以下M行,每行三个整数A、B和C,表示路点A和B之间有一条小路相连,且通过它需要的时间为C。
输入数据保证两路点间最多只有一条小路相连,且戈壁和花园的路点是连通的。

输出格式

一个整数,表示使S到T之间最短路增长所需要的最少的小xie的数目。

输入样例

5 5 1 5
1 2 1
2 3 3
1 4 2
4 3 2
5 1 1

输出样例

1

数据范围

对于30%的数据,满足N≤10,M≤50。
对于50%的数据,满足N≤200,M≤10000。
对于全部的数据,满足N≤1000,M≤499500,0<C≤1000000。

题解

虽然我不懂为什么noip模拟赛会考到最小割,不过幸好还是A了。

 #include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<cmath>
#include<algorithm>
#define inf 1e15
#define ll long long
using namespace std;
int n,m,S,T,hd[1002],ct;
struct bian{int to,nx; ll v;} E[999002];
//---------------------------------------
ll dis[1002];
struct dui{int w; ll d;} q[20002];
int pd[1002],size,from[1002][1002];
//----------------------------------------
int head[1002],zz=1,dui[1002],h[1002],in[1002];
ll ans;
struct liu{int to,nx,v;} e[999002];
//--------------------------------------------------------------------------
void insert1(int x,int y,ll z)
{
	ct++; E[ct].to=y; E[ct].v=z; E[ct].nx=hd[x]; hd[x]=ct;
	ct++; E[ct].to=x; E[ct].v=z; E[ct].nx=hd[y]; hd[y]=ct;
}
void init()
{
	scanf("%d%d%d%d",&n,&m,&S,&T);
	int i,x,y; ll z;
	for(i=1;i<=m;i++)
	   {scanf("%d%d%I64d",&x,&y,&z);
	    insert1(x,y,z);
	   }
}
void heapfy(int x)
{
	int l=x<<1,r=l+1,minx=x;
	if(l<=size&&q[l].d<q[x].d) minx=l;
	if(r<=size&&q[r].d<q[minx].d) minx=r;
	if(minx!=x)
	   {swap(q[minx],q[x]); heapfy(minx);}
}
void del()
{
	q[1]=q[size]; size--;
	if(size) heapfy(1);
}
void weih(int x)
{
	if(x<=1) return ;
	int i=x>>1;
	if(q[i].d>q[x].d) swap(q[i],q[x]);
	weih(i);
}
void dijkstra()
{
	int i,x,p;
	for(i=1;i<=n;i++) dis[i]=inf;
	size=1; q[1].w=S; q[1].d=dis[S]=0;
	while(size)
	   {x=q[1].w; del();
	    if(pd[x]) continue;
	    pd[x]=1;
	    for(i=hd[x];i;i=E[i].nx)
	       {p=E[i].to;
			if(dis[p]>dis[x]+E[i].v)
			   {dis[p]=dis[x]+E[i].v;
			    from[p][0]=1; from[p][from[p][0]]=x;
			    size++; q[size].w=p; q[size].d=dis[p]; weih(size);
			   }
			else if(dis[p]==dis[x]+E[i].v)
			   {from[p][0]++; from[p][from[p][0]]=x;}
		   }
	   }
}
//------------------------------------------------------------------------------
void insert2(int x,int y)
{
	zz++; e[zz].to=y; e[zz].v=1; e[zz].nx=head[x]; head[x]=zz;
	zz++; e[zz].to=x; e[zz].v=0; e[zz].nx=head[y]; head[y]=zz;
}
void rebuild()
{
	int i,j,t=0,w=1;
	dui[t]=T; in[T]=1;
	while(t<w)
	   {i=dui[t]; t++;
		for(j=1;j<=from[i][0];j++)
	       {if(!in[from[i][j]]) {dui[w]=from[i][j]; in[from[i][j]]=1; w++;}
			insert2(from[i][j],i);
		   }
	   }
}
bool bfs()
{
	int t=0,w=1,x,i,p;
	memset(h,-1,sizeof(h));
	dui[0]=S; h[S]=0;
	while(t!=w)
	   {x=dui[t]; t=(t+1)%n;
	    for(i=head[x];i;i=e[i].nx)
	       {p=e[i].to;
			if(h[p]<0&&e[i].v)
			   {h[p]=h[x]+1;
			    dui[w]=p; w=(w+1)%n;
			   }
		   }
	   }
	if(h[T]<0) return false;
	else return true;
}
int dfs(int x,int f)
{
	if(x==T) return f;
	int i,rest,usd=0,p;
	for(i=head[x];i;i=e[i].nx)
	   {p=e[i].to;
	    if(h[p]==h[x]+1&&e[i].v)
	       {rest=f-usd;
		    rest=dfs(p,min(e[i].v,rest));
		    e[i].v-=rest;
		    e[i^1].v+=rest;
		    usd+=rest;
		    if(usd==f) return f;
		   }
	   }
	if(!usd) h[x]=-1;
	return usd;
}
void dinic()
{
	while(bfs()) ans+=dfs(S,0x7fffffff); 
	printf("%I64d\n",ans);
}
int main()
{
	freopen("greendam.in","r",stdin);
	freopen("greendam.out","w",stdout);
	init(); dijkstra();
	rebuild(); dinic();
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值