这是一道水题。。
题意有点羞涩难懂,自己慢慢看吧。。
只需要一开始跑最短路然后建图网络流就好了。。
然后呢,最短路可以有多条,一开始我的做法比较傻,开了个数组来存。。
然后时间很慢,空间很大,编译TLE了
#include<cstdio>
#include<queue>
#include<algorithm>
#include<cstdlib>
#include<cstring>
using namespace std;
typedef long long LL;
const LL N=505*2;
const LL M=100005*2;
const LL MAX=1LL<<60;
struct qq{LL x,y,z,last,other;}s[M*2];
LL num,last[N];
LL n,m;
void init (LL x,LL y,LL z)
{
num++;
s[num].x=x;s[num].y=y;s[num].z=z;
s[num].last=last[x];
last[x]=num;
}
LL tt[N][M];//这个点的最短路都可以从哪些点多来
LL t[N];
priority_queue < pair <LL,LL >,vector<pair<LL,LL> >,greater<pair<LL,LL> > > q;
bool in[N];
void SPFA ()
{
memset(t,127,sizeof(t));
memset(in,false,sizeof(in));
q.push(make_pair(0,1));t[1]=0;in[1]=true;
while (!q.empty())
{
int x=q.top().second;q.pop();
for (LL u=last[x];u!=-1;u=s[u].last)
{
LL y=s[u].y;
if (t[y]>t[x]+s[u].z)
{
t[y]=t[x]+s[u].z;
tt[y][0]=1;tt[y][1]=x;
if (in[y]==true) continue;
in[y]=true;
q.push(make_pair(t[y],y));
}
else if (t[y]==t[x]+s[u].z)
{
tt[y][0]++;
tt[y][tt[y][0]]=x;
}
}
in[x]=false;
}
}
void dfs (LL x)
{
if (x==1) return ;
if (in[x]==true) return ;
in[x]=true;
for (LL u=1;u<=tt[x][0];u++)
{
init(tt[x][u]+n,x,MAX);s[num].other=num+1;
init(x,tt[x][u]+n,0);s[num].other=num-1;
dfs(tt[x][u]);
}
}
LL h[N];
LL st1,ed1;
LL Q[N];
bool bt ()
{
memset(h,0,sizeof(h));
LL st=1,ed=2;
h[st1]=1;
Q[st]=st1;
while (st!=ed)
{
LL x=Q[st];
for (LL u=last[x];u!=-1;u=s[u].last)
{
LL y=s[u].y;
if (s[u].z>0&&h[y]==0)
{
h[y]=h[x]+1;
Q[ed]=y;
ed++;
}
}
st++;
}
if (h[ed1]!=0) return true;
return false;
}
LL mymin (LL x,LL y)
{
return x<y?x:y;
}
LL find (LL x,LL f)
{
if (x==ed1) return f;
LL s1=0,t;
for (LL u=last[x];u!=-1;u=s[u].last)
{
LL y=s[u].y;
if (s[u].z>0&&h[y]==(h[x]+1)&&s1<f)
{
t=find(y,mymin(s[u].z,f-s1));
s1+=t;
s[u].z-=t;
s[s[u].other].z+=t;
}
}
if (s1==0) h[x]=0;
return s1;
}
int main()
{
num=0;memset(last,-1,sizeof(last));
scanf("%lld%lld",&n,&m);
for (LL u=1;u<=m;u++)
{
LL x,y,z;
scanf("%lld%lld%lld",&x,&y,&z);
init(x,y,z);init(y,x,z);
}
SPFA();
num=0;memset(last,-1,sizeof(last));
memset(in,false,sizeof(in));
dfs(n);
for (LL u=1;u<=n;u++)
{
LL a;
scanf("%lld",&a);
if (u==1||u==n) continue;
init(u,u+n,a);s[num].other=num+1;
init(u+n,u,0);s[num].other=num-1;
}
st1=1+n;ed1=n;
LL ans=0;
while (bt()==true)
ans=ans+find(st1,MAX);
printf("%lld",ans);
return 0;
}
那这怎么办呢,我们发现,我们并不要存下来,我们只需要在跑完之后看一次就好了。。
于是就有了如下版本,SPFA还是要加堆优化
#include<cstdio>
#include<queue>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#define swap(x,y) {int tt=x;x=y;y=tt;}
using namespace std;
typedef long long LL;
const int N=505*2;
const int M=100005;
const LL MAX=1LL<<60;
struct qq{int x,y,last,other;LL z;}s[M*4];
int num,last[N];
int n,m;
void init (int x,int y,LL z)
{
num++;
s[num].x=x;s[num].y=y;s[num].z=z;
s[num].last=last[x];
last[x]=num;
}
int X[M],Y[M];
LL Z[M];
LL t[N];
priority_queue < pair <LL,int >,vector<pair<LL,int> >,greater<pair<LL,int> > > q;
bool in[N];
void SPFA ()
{
memset(t,127,sizeof(t));
memset(in,false,sizeof(in));
q.push(make_pair(0,1));t[1]=0;in[1]=true;
while (!q.empty())
{
int x=q.top().second;q.pop();
for (LL u=last[x];u!=-1;u=s[u].last)
{
LL y=s[u].y;
if (t[y]>t[x]+s[u].z)
{
t[y]=t[x]+s[u].z;
if (in[y]==true) continue;
in[y]=true;
q.push(make_pair(t[y],y));
}
}
in[x]=false;
}
}
void dfs ()
{
for (int u=1;u<=m;u++)
{
if (t[X[u]]+Z[u]==t[Y[u]])
{
init(X[u]+n,Y[u],MAX);s[num].other=num+1;
init(Y[u],X[u]+n,0);s[num].other=num-1;
}
swap(X[u],Y[u]);
if (t[X[u]]+Z[u]==t[Y[u]])
{
init(X[u]+n,Y[u],MAX);s[num].other=num+1;
init(Y[u],X[u]+n,0);s[num].other=num-1;
}
}
/*if (x==1) return ;
if (in[x]==true) return ;
in[x]=true;
for (int u=1;u<=tt[x][0];u++)
{
init(tt[x][u]+n,x,MAX);s[num].other=num+1;
init(x,tt[x][u]+n,0);s[num].other=num-1;
dfs(tt[x][u]);
}*/
}
int h[N];
int st1,ed1;
int Q[N];
bool bt ()
{
memset(h,0,sizeof(h));
int st=1,ed=2;
h[st1]=1;
Q[st]=st1;
while (st!=ed)
{
int x=Q[st];
for (int u=last[x];u!=-1;u=s[u].last)
{
int y=s[u].y;
if (s[u].z>0&&h[y]==0)
{
h[y]=h[x]+1;
Q[ed]=y;
ed++;
}
}
st++;
}
if (h[ed1]!=0) return true;
return false;
}
LL mymin (LL x,LL y)
{
return x<y?x:y;
}
LL find (int x,LL f)
{
if (x==ed1) return f;
LL s1=0,t;
for (int u=last[x];u!=-1;u=s[u].last)
{
int y=s[u].y;
if (s[u].z>0&&h[y]==(h[x]+1)&&s1<f)
{
t=find(y,mymin(s[u].z,f-s1));
s1+=t;
s[u].z-=t;
s[s[u].other].z+=t;
}
}
if (s1==0) h[x]=0;
return s1;
}
int main()
{
num=0;memset(last,-1,sizeof(last));
scanf("%d%d",&n,&m);
for (int u=1;u<=m;u++)
{
int x,y;
LL z;
scanf("%d%d%lld",&X[u],&Y[u],&Z[u]);
init(X[u],Y[u],Z[u]);init(Y[u],X[u],Z[u]);
}
SPFA();
num=0;memset(last,-1,sizeof(last));
dfs();
for (int u=1;u<=n;u++)
{
LL a;
scanf("%lld",&a);
if (u==1||u==n) continue;
init(u,u+n,a);s[num].other=num+1;
init(u+n,u,0);s[num].other=num-1;
}
st1=1+n;ed1=n;
LL ans=0;
while (bt()==true)
ans=ans+find(st1,MAX);
printf("%lld",ans);
return 0;
}
顺便,通过这题,我学会了dijkstra,其实和上面那个有堆优化的SPFA差不多,应该还快些,我看了一下,时间复杂度应该是 O(nlogn) ,我也没查过资料QuQ
#include<cstdio>
#include<queue>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#define swap(x,y) {int tt=x;x=y;y=tt;}
using namespace std;
typedef long long LL;
const int N=505*2;
const int M=100005;
const LL MAX=1LL<<60;
struct qq{int x,y,last,other;LL z;}s[M*4];
int num,last[N];
int n,m;
void init (int x,int y,LL z)
{
num++;
s[num].x=x;s[num].y=y;s[num].z=z;
s[num].last=last[x];
last[x]=num;
}
int X[M],Y[M];
LL Z[M];
LL t[N];
priority_queue < pair <LL,int >,vector<pair<LL,int> >,greater<pair<LL,int> > > q;
bool in[N];
void dijkstra ()
{
memset(t,127,sizeof(t));
memset(in,false,sizeof(in));
q.push(make_pair(0,1));t[1]=0;
while (!q.empty())
{
int x=q.top().second;q.pop();
if (in[x]==true) continue;
in[x]=true;
for (int u=last[x];u!=-1;u=s[u].last)
{
int y=s[u].y;
if (t[y]>t[x]+s[u].z)
{
t[y]=t[x]+s[u].z;
q.push(make_pair(t[y],y));
}
}
}
//printf("YES:%lld\n",t[n]);
}
void dfs ()
{
for (int u=1;u<=m;u++)
{
if (t[X[u]]+Z[u]==t[Y[u]])
{
init(X[u]+n,Y[u],MAX);s[num].other=num+1;
init(Y[u],X[u]+n,0);s[num].other=num-1;
}
swap(X[u],Y[u]);
if (t[X[u]]+Z[u]==t[Y[u]])
{
init(X[u]+n,Y[u],MAX);s[num].other=num+1;
init(Y[u],X[u]+n,0);s[num].other=num-1;
}
}
/*if (x==1) return ;
if (in[x]==true) return ;
in[x]=true;
for (int u=1;u<=tt[x][0];u++)
{
init(tt[x][u]+n,x,MAX);s[num].other=num+1;
init(x,tt[x][u]+n,0);s[num].other=num-1;
dfs(tt[x][u]);
}*/
}
int h[N];
int st1,ed1;
int Q[N];
bool bt ()
{
memset(h,0,sizeof(h));
int st=1,ed=2;
h[st1]=1;
Q[st]=st1;
while (st!=ed)
{
int x=Q[st];
for (int u=last[x];u!=-1;u=s[u].last)
{
int y=s[u].y;
if (s[u].z>0&&h[y]==0)
{
h[y]=h[x]+1;
Q[ed]=y;
ed++;
}
}
st++;
}
if (h[ed1]!=0) return true;
return false;
}
LL mymin (LL x,LL y)
{
return x<y?x:y;
}
LL find (int x,LL f)
{
if (x==ed1) return f;
LL s1=0,t;
for (int u=last[x];u!=-1;u=s[u].last)
{
int y=s[u].y;
if (s[u].z>0&&h[y]==(h[x]+1)&&s1<f)
{
t=find(y,mymin(s[u].z,f-s1));
s1+=t;
s[u].z-=t;
s[s[u].other].z+=t;
}
}
if (s1==0) h[x]=0;
return s1;
}
int main()
{
num=0;memset(last,-1,sizeof(last));
scanf("%d%d",&n,&m);
for (int u=1;u<=m;u++)
{
int x,y;
LL z;
scanf("%d%d%lld",&X[u],&Y[u],&Z[u]);
init(X[u],Y[u],Z[u]);init(Y[u],X[u],Z[u]);
}
dijkstra();
num=0;memset(last,-1,sizeof(last));
dfs();
for (int u=1;u<=n;u++)
{
LL a;
scanf("%lld",&a);
if (u==1||u==n) continue;
init(u,u+n,a);s[num].other=num+1;
init(u+n,u,0);s[num].other=num-1;
}
st1=1+n;ed1=n;
LL ans=0;
while (bt()==true)
ans=ans+find(st1,MAX);
printf("%lld",ans);
return 0;
}