luogu P2770 航空路线问题

题目链接

luogu P2770 航空路线问题

题解

求两条点数最多的互不相交路径
拆点限流,连流量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; 
} 

猜你喜欢

转载自www.cnblogs.com/sssy/p/9357034.html
今日推荐