发现自己是所有提交里跑的最快的,于是说一下自己的建模方式。
不要向其他题解那样每条航线拆成两个点,而是每条航线是一个点,用 vector<flight>arr[i] 存一下以 i 号城市为起点的所有航线,( flight 是自己定义的结构体,存终点、出发时间、到达时间、乘客上限),对每个 arr[i] 内部排个序(出发早的航线在前),一个 arr[i] 内部的每个航线和后一个航线连一条无限容量的边,表示可以在这个起始城市呆多久都行。
对于每个航线 t ,去终点对应的 arr[i] 里找第一个符合要求的航线(换乘来得及的),连一条容量为航线 t 乘客上限的边即可。
最后别忘了源点和汇点,很容易处理,不细讲了。
和其他题解相比,好处是点数减半,边数减了很多很多。所以快。
//#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<algorithm>
#include<vector>
#include<string.h>
#include<queue>
#include<assert.h>
#include<stack>
#include<map>
using namespace std;
const int maxn = 1e4+ 5;
const int INF = 1e8;
struct edge
{
int from, to, cap, flow;
};
struct dinic
{
int d[maxn];
int vis[maxn];
int s, t;
int cur[maxn];
vector<int> G[maxn];
vector<edge> edges;
void init()
{
edges.clear();
for (int i = 0; i < maxn; i++)G[i].clear();
}
void add_edge(int from,int to,int c)
{
edges.push_back(edge{ from,to,c,0 });
edges.push_back(edge{ to,from,0,0 });
int m = edges.size();
G[from].push_back(m - 2);
G[to].push_back(m - 1);
}
bool bfs()
{
d[s] = 0;
memset(vis, 0, sizeof(vis));
vis[s] = 1;
queue<int> q; q.push(s);
while (!q.empty())
{
int x = q.front(); q.pop();
for (int i = 0; i < G[x].size(); i++)
{
edge& e = edges[G[x][i]];
int v = e.to;
if (!vis[v] && e.cap > e.flow)
{
vis[v] = 1;
d[v] = d[x] + 1;
q.push(v);
}
}
}
return vis[t];
}
int dfs(int u, int a)
{
if (u == t || a == 0)return a;
int flow = 0, f;
for (int& i = cur[u]; i < G[u].size(); i++)
{
edge& e = edges[G[u][i]];
int v = e.to;
if (d[v] == d[u] + 1 && (f = dfs(v, min(a, e.cap - e.flow))) > 0)
{
flow += f;
a -= f;
edges[G[u][i]].flow += f;
edges[G[u][i]^1].flow -= f;
if (a == 0)return flow;
}
}
return flow;
}
int maxflow(int s, int t)
{
this->s = s; this->t = t;
int flow = 0;
while (bfs())
{
memset(cur, 0, sizeof(cur));
flow += dfs(s, INF);
}
return flow;
}
}di;
int n,m;
map<string, int> dict;
string arr[155];
int tt;
struct flight
{
int t1, t2;
int num;
int dest;
int id;
bool operator < (const flight& t)const
{
return t1 < t.t1;
}
};
vector<flight> city[155];
int cnt;
int hhmm2t(int x)
{
int h = x / 100;
int m = x % 100;
return h * 60 + m;
}
void init()
{
dict.clear(); di.init();
cnt = 2;
for (int i = 0; i < 155; i++)city[i].clear();
string str;
cin >> str; arr[1] = str; dict[str] = 1;
cin >> str; arr[2] = str; dict[str] = 2;
cin >> tt; tt = hhmm2t(tt);
cin >> m;
for (int i = 0; i < m; i++)
{
string a, b;
int num, t1, t2;
cin >> a >> b >> num >> t1 >> t2;
t1 = hhmm2t(t1); t2 = hhmm2t(t2);
if (!dict.count(a))
{
cnt++;
dict[a] = cnt;
arr[cnt] = a;
}
if (!dict.count(b))
{
cnt++;
dict[b] = cnt;
arr[cnt] = b;
}
int start = dict[a];
int dest = dict[b];
if (start == 2)continue;
city[start].push_back(flight{ t1,t2,num,dest,-1 });
}
assert(cnt == n);
for (int i = 1; i <= cnt; i++)
{
sort(city[i].begin(), city[i].end());
}
int sz = 0;
for (int i = 1; i <= cnt; i++)
{
for (int g = 0; g < city[i].size(); g++)
{
flight& f = city[i][g];
sz++;
f.id = sz;
}
}
int T = sz + 1;
for (int i = 1; i <= cnt; i++)
{
for (int g = 0; g+1 < city[i].size(); g++)
{
flight& f = city[i][g];
di.add_edge(f.id, f.id + 1, INF);
}
}
for (int i = 1; i <= cnt; i++)
{
for (int g = 0; g < city[i].size(); g++)
{
flight& f = city[i][g];
int de = f.dest;
if (de == 2&&f.t2<=tt) //
{
di.add_edge(f.id, T, f.num);
}
else
{
for (int j = 0; j < city[de].size(); j++)
{
if (f.t2 + 30 <= city[de][j].t1)
{
di.add_edge(f.id, city[de][j].id, f.num);
break;
}
}
}
}
}
di.add_edge(0, 1, INF);
cout<<di.maxflow(0,T)<<endl;
}
int main()
{
while (cin >> n)
{
init();
}
}