题目链接
题解
求两条点数最多的互不相交路径
拆点限流,连流量1费用2的边,起.终点流量为2的边
代码
#include<bits/stdc++.h>
using namespace std;
inline int read() {
int x = 0,f = 1; char c = getchar();
while(c < '0' || c > '9')c = getchar();
while(c <= '9' && c >= '0') x = x * 10 + c - '0',c = getchar();
return x * f ;
}
#define INF 0x7fffffff
const int maxn = 207;
const int maxm = 24007;
struct node {
int u,v,cost,flow,next;
node(int u = 0,int v = 0,int cost = 0,int flow = 0,int next = 0) : u(u), v(v), cost(cost), flow(flow), next(next) {}
} edge[maxm << 1];
int head[maxn],num = 1;
void add_edge(int u,int v,int cost,int flow) { edge[++ num] = node(u,v,cost,flow,head[u]); head[u] = num; }
queue<int>q;
bool vis[maxn];
int dis[maxn],path[maxn],pre[maxn];
int n,m,S,T;
bool spfa() {
memset(dis,0x3f,sizeof dis);pre[S] = -1;
q.push(S),vis[S]=true,dis[S]=0;
while(!q.empty()) {
int u = q.front(); q.pop();
for(int i = head[u];i;i = edge[i].next) {
int v = edge[i].v;
if(edge[i].flow > 0 && dis[v] > dis[u] + edge[i].cost) {
dis[v] = edge[path[v] = i].cost + dis[pre[v] = u];
if(!vis[v]) q.push(v) , vis[v]=true;
}
} vis[u] = false;
}
return dis[T] != 0x3f3f3f3f;
}
int maxflow,mincost;
void calc() {
int f = INF;
for(int u = T;u != S;u = pre[u]) f = min(f,edge[path[u]].flow);
maxflow += f,mincost += dis[T] * f;
for(int u = T;u != S;u = pre[u]) {
edge[path[u]].flow -= f,
edge[path[u] ^ 1].flow += f;
}
}
void MCMF() {
while(spfa()) calc();
}
bool flag[maxn];
map<string,int>mp;
map<int,string>rmp;
int main() {
n = read(),m = read();
S = 1,T = n << 1;
for(int i = 1;i <= n;i ++) {
string s;
cin >> s; mp[s] = i; rmp[i] = s;
if(i == 1 || i == n) add_edge(i,i + n,-1,2) , add_edge(i + n,i,1,0);
else add_edge(i,i+n,-1,1),add_edge(i+n,i,1,0);
}
for(int i = 1;i <= m;i ++) {
string a,b;
cin >> a >> b;
int u = mp[a],v = mp[b];
if(v < u) swap(u , v);
if(u == 1 && v == n) add_edge(u + n,v,0,2) , add_edge(v,u + n,0,0);
else add_edge(u + n,v,0,1) , add_edge(v,u + n,0,0);
}
MCMF();
if(edge[2].flow != 0) { puts("No Solution!"); return 0; }
cout << -mincost - 2 << endl << rmp[1] << endl;
for(int i = head[n + 1];i;i = edge[i].next)
if(! edge[i].flow && ! (i & 1)) {
for(int v = edge[i].v, j ; v ;) {
cout << rmp[v] << endl;
flag[v] = true;
for(j = head[v + n],v = 0;j;j = edge[j].next)
if(! edge[j].flow && ! (j & 1)) {
v = edge[j].v;
break;
}
}
break;
}
for(int i = head[n];i;i = edge[i].next)
if(! edge[i ^ 1].flow && (i & 1) && ! flag[edge[i].v - n]) {
for(int v = edge[i].v - n,j;v;) {
cout << rmp[v] << endl;flag[v] = true;
for(j = head[v],v = 0;j;j = edge[j].next)
if(! edge[j ^ 1].flow && (j & 1)) {
v = edge[j].v - n;
break;
}
}
break;
}
return 0;
}