标签:目的 sum amp 经营 金融 esc hint space bzoj
约定:
2 <= N <= 50
1 <= M <= 2450
1 <= T <= 50
1 <= X,Y <= N
X != Y
1 <= Z <= 50
题解:我们假设在tim时所有人都能到达终点,于是我们枚举tim,将每个点拆成tim个,然后连边跑最大流,若流量=T,说明tim就是答案
具体方法:用(i,j)表示将原来的i号节点拆成第j个点
1.S -> (0,0) 流量T
2.(i,j-1) -> (i,j) 流量∞
3.对于边(a,b,c) (a,j-1) -> (b,j) 流量c
4.(n,j) -> T 流量T
由于本人觉得点数比较多,感到很虚,所以用了动态加边的最大流,56ms飞起~
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#define P(A,B) ((B)*n+A)
using namespace std;
int to[1000000],next[1000000],val[1000000],d[50010],head[50010],pa[2500],pb[2500],pc[2500];
int n,m,t,cnt,ans,sum,S,T,tim;
queue<int> q;
int rd()
{
int ret=0,f=1; char gc=getchar();
while(gc<‘0‘||gc>‘9‘) {if(gc==‘-‘)f=-f; gc=getchar();}
while(gc>=‘0‘&&gc<=‘9‘) ret=ret*10+gc-‘0‘,gc=getchar();
return ret*f;
}
void add(int a,int b,int c)
{
to[cnt]=b,val[cnt]=c,next[cnt]=head[a],head[a]=cnt++;
to[cnt]=a,val[cnt]=0,next[cnt]=head[b],head[b]=cnt++;
}
int bfs()
{
int i,u;
memset(d,0,sizeof(d));
while(!q.empty()) q.pop();
d[S]=1,q.push(S);
while(!q.empty())
{
u=q.front(),q.pop();
for(i=head[u];i!=-1;i=next[i])
{
if(!d[to[i]]&&val[i])
{
d[to[i]]=d[u]+1;
if(to[i]==T) return 1;
q.push(to[i]);
}
}
}
return 0;
}
int dfs(int x,int mf)
{
if(x==T) return mf;
int i,temp=mf,k;
for(i=head[x];i!=-1;i=next[i])
{
if(d[to[i]]==d[x]+1&&val[i])
{
k=dfs(to[i],min(temp,val[i]));
if(!k) d[to[i]]=0;
val[i]-=k,val[i^1]+=k,temp-=k;
if(!temp) break;
}
}
return mf-temp;
}
int main()
{
n=rd(),m=rd(),t=rd(),tim=n+t;
S=0,T=n*(tim+1)+1;
memset(head,-1,sizeof(head));
add(S,1,t);
int i,j,k,a,b,c;
for(i=1;i<=m;i++) pa[i]=rd(),pb[i]=rd(),pc[i]=rd();
for(i=1;i<=tim;i++)
{
for(j=1;j<=m;j++) add(P(pa[j],i-1),P(pb[j],i),pc[j]);
for(j=1;j<=n;j++) add(P(j,i-1),P(j,i),1<<30);
add(P(n,i),T,t);
while(bfs()) sum+=dfs(S,1<<30);
if(sum==t)
{
printf("%d",i);
return 0;
}
}
}
【BZOJ1570】[JSOI2008]Blue Mary的旅行 动态加边网络流
标签:目的 sum amp 经营 金融 esc hint space bzoj
原文地址:http://www.cnblogs.com/CQzhangyu/p/6855711.html