航空路线问题
航空路线问题
做的第三道二十四题qwq,
前两道都没发 \(blog\) .
原因是一道太水了(裸二分图最大匹配),
还有一道一会再写qwq(虽然过了好久了).
这道题是某 HwH 聚神随机跳题跳到的,
鉴于我学网络流比他有经验(bushi),
于是乎他便来找我qwq,
但是由于当时刚好该放学了(其实是因为我在搞事system),
我就随便一看,
结果发现是道水题bushi,
然后秒了qwq.
这道题其实非常简单(不知道为什么评紫?!),
首先,
因为我们一去一回,
所以就相当于去两趟,
但是要走不同的路.
所以我们从源点(可以是 \(1\) 也可以再开一个点)建一条容量为 \(2\) 的边,
这不就好起来了?
然后正常建边,
每条边的容量和费用都为 \(1\) ,
跑一边最大费用最大流就好了.
于是我发现我 \(WA\) 了(真不戳).
后来发现要拆点,
因为每个城市只能走一次.
ok, very good!
这下好了,
全都是unexpected order.
怎么多输出了一个 "No Solution!" ?
然后又双叒叕读了一遍题,
发现无解的情况并非是无法回来(最大流为 \(1\)),
而是无法到达(最大流为 \(0\)).
然后就ok了,
只差顺序了.
这个该死的 \(DFS\) 我愣是搞了好几天.
然后今天上午地理学考模拟考试的时候,
由于题太水(nan)了,
一会就水完了,
然后就想到了这个题,
我就花了一个图,
发现如果是从编号大的点向编号小的点走,
只能是拆点拆出来的点(想一想为什么),
因为我们如果是从编号大的向编号小的走,
且这两个点不是一个城市的话,
那么我们一定是从东向西走,
而按照我们的思路来,
则是应该从东往西走两趟,
所以我们走的这条边一定是我们没走的(尽管它的流量已经达到了容量),
于是乎就过啦!
\(code:\)
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <map>
using namespace std;
const int maxn = 2e2 + 5, maxm = 2e4 + 4;
int n, m, s, t, flow[maxn], d[maxn], pre[maxn], num[maxn];
int tot = 1, to[maxm], cap[maxm], cost[maxm], nxt[maxm], head[maxn];
string name[maxn];
int maxcost, maxflow;
bool vis[maxn], use[maxn];
queue <int> q;
map <string, int> mp;
int read(){
int x = 0;
char ch = getchar();
while (ch < '0' || ch > '9') ch = getchar();
while (ch >= '0' && ch <= '9'){
x = (x << 3) + (x << 1) + (ch ^ 48);
ch = getchar();
}
return x;
}
void add(int u, int v, int w, int c){
to[++tot] = v, cap[tot] = w, cost[tot] = c, nxt[tot] = head[u], head[u] = tot;
to[++tot] = u, cap[tot] = 0, cost[tot] = -c, nxt[tot] = head[v], head[v] = tot;
}
bool SPFA(){
memset(d, -1, sizeof(d));
memset(flow, 0x3f, sizeof(flow));
memset(vis, 0, sizeof(vis));
q.push(s);
d[s] = 0; pre[t] = -1;
while (q.size()){
int x = q.front(); q.pop();
vis[x] = 0;
for (int i = head[x]; i; i = nxt[i]){
int y = to[i], z = cost[i];
if (d[y] < d[x] + z && cap[i]){
d[y] = d[x] + z;
pre[y] = x;
num[y] = i;
flow[y] = min(flow[x], cap[i]);
if (vis[y] == 0){
q.push(y);
vis[y] = 1;
}
}
}
}
return pre[t] != -1;
}
void MCMF(){
while (SPFA()){
int now = t;
maxflow += flow[t];
maxcost += flow[t] * d[t];
while (now != s){
cap[num[now]] -= flow[t];
cap[num[now] ^ 1] += flow[t];
now = pre[now];
}
}
}
void DFS1(int x){
if (x <= n) cout << name[x] << "\n";
use[x] = 1;
for (int i = head[x]; i; i = nxt[i]){
int y = to[i];
if (cap[i] == 0 && !(y > x && y - x != n)){
use[y] = 1;
DFS1(y);
break;
}
}
}
void DFS2(int x){
for (int i = head[x]; i; i = nxt[i]){
int y = to[i];
if (cap[i] == 0 && !(y > x && y - x != n) && use[y] == 0){
use[y] = 1;
DFS2(y);
break;
}
}
if (x <= n) cout << name[x] << "\n";
use[x] = 1;
}
int main(){
n = read(), m = read(); s = 1, t = n;
for (int i = 1; i <= n; i++){
cin >> name[i];
mp[name[i]] = i;
}
add(1, n + 1, 2, 0);
for (int i = 2; i < n; i++) add(i, i + n, 1, 1);
for (int i = 1; i <= m; i++){
string x, y;
cin >> x >> y;
int u = mp[x], v = mp[y];
if (u > v) swap(u, v);
u += n;
add(u, v, 1, 0);
}
MCMF();
if (maxflow == 0){
printf("No Solution!");
return 0;
}
printf("%d\n", maxcost + 2);
cout << name[1] << "\n";
DFS1(1 + n);
DFS2(1 + n);
cout << name[1] << "\n";
return 0;
}
qwq
看不见我看不见我看不见我