Avoiding the Apocalypse
题目链接: Avoiding the Apocalypse Gym - 101512A
题意
有n个点,开始i点上有g个人,每条路是a通向b,花费t秒,每秒可以通过t人,有m个终点,问在s秒内最多多少人到达终点
思路
因为单向边的有向性,与时间的有向性相呼应,所以我们可以将其拆点,将时间转换成空间,这题的时间和点数都挺少的,所以,我们用空间来换时间完全可以。
注意在开始状态时,一定要将每个点扩充。最后跑一下最大流即可。
代码
#include <bits/stdc++.h>
using namespace std;
#define rep(i,j,k) for(int i = (int)j;i <= (int)k;i ++)
#define per(i,j,k) for(int i = (int)j;i >= (int)k;i --)
#define debug(x) cerr<<#x<<" = "<<(x)<<endl
#define mmm(a,b) memset(a,b,sizeof(a))
#define pb push_back
typedef double db;
typedef long long ll;
const int MAXN = (int)5e5+7;
const int INF = (int)0x3f3f3f3f;
// 用于表示表示边的结构体(终点、容量、反向边)
struct edge{
int to,cap,rev;
edge(int to = 0,int cap = 0,int rev = 0):to(to),cap(cap),rev(rev){}
};
int N,M;
vector<edge> G[MAXN];
int level[MAXN]; //顶点到源点的距离标号
int iter[MAXN]; //当前弧,在其之前的边已经没有用了
//向图中增加一条从s到t容量为cap的边
void add_edge(int from,int to,int cap) {
G[from].pb(edge(to,cap,G[to].size()));
G[to ].pb(edge(from,0,G[from].size()-1));
}
//通过BFS计算从源点出发的距离标号
void bfs(int s){
mmm(level,-1);
queue<int> qu;
level[s] = 0;
qu.push(s);
while (!qu.empty()) {
int v = qu.front(); qu.pop();
rep(i,0,G[v].size()-1) {
edge &e = G[v][i];
if (e.cap > 0 && level[e.to] < 0) {
level[e.to] = level[v] + 1;
qu.push(e.to);
}
}
}
}
//通过DFS寻找增广路
int dfs(int v,int t,int f) {
if (v == t) return f;
for (int &i = iter[v];i < G[v].size();i ++) {
edge &e = G[v][i];
if (e.cap > 0 && level[v] < level[e.to]) {
int d = dfs(e.to,t,min(f,e.cap));
if (d > 0) {
e.cap -= d;
G[e.to][e.rev].cap += d;
return d;
}
}
}
return 0;
}
//求解从s到t的最大流
int max_flow(int s,int t){
int flow = 0;
for (;;) {
bfs(s);
if (level[t] < 0) return flow;
mmm(iter,0);
int f;
while ((f = dfs(s,t,INF)) > 0)
flow += f;
}
}
void init(){
rep(i,1,N*105) G[i].clear();
}
int main()
{
int T,n,ini,g,step,m;
int sp,tp;
scanf("%d",&T);
while (T --) {
scanf("%d %d %d %d",&n,&ini,&g,&step);
sp = (n+1)*105+1;tp = sp+1;N = n+2;
init();
add_edge(sp,ini*105,g);
for (int i = 1;i <= n;i ++) {
for (int j = 0;j < step;j ++) {
add_edge(i*105+j,i*105+j+1,g); //t0 -> T-t0
}
}
scanf("%d",&m);
for (int i = 0;i < m;i ++) {
int x;
scanf("%d",&x);
add_edge(x*105+step,tp,g);
}
int r;
scanf("%d",&r);
for (int i = 0;i < r;i ++) {
int a,b,p,t;
scanf("%d %d %d %d",&a,&b,&p,&t);
for (int j = 0;j+t <= step;j ++){
add_edge(a*105+j,b*105+j+t,p);
}
}
int ans = max_flow(sp,tp);
printf("%d\n",ans);
}
}