POJ-1087 A Plug for UNIX 网络流

本文探讨了如何通过构建图结构来处理插座之间的传递闭包问题,并利用Floyd算法进行路径优化。详细介绍了从输入数据到图构建、闭包计算再到应用Floyd算法的过程,最终求解最优路径问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

根据关系建一个图,然后就是后面的插座的传递闭包,一个floyd构边。

代码如下:

#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <map>
#include <string>
#define INF 0x3fffffff
#define CN(x) (255+(x))
#define MN(x) (555+(x))
#define MAXN 500
using namespace std;

int N, M, K, rec[MAXN], idx, cnt;
int head[1000], dis[1000], que[1000], front, tail;
const int SS = 0, TT = 998;
bool R[505][505];

map<string,int>mp;

struct Edge {
    int v, cap, next;
}e[500000];

void addedge(int a, int b, int cap) {
    ++idx;
    e[idx].v = b, e[idx].cap = cap;
    e[idx].next = head[a], head[a] = idx;
    ++idx;
    e[idx].v = a, e[idx].cap = 0;
    e[idx].next = head[b], head[b] = idx;
}

bool bfs() {
    int pos;
    memset(dis, 0xff, sizeof (dis));
    dis[SS] = front = tail = 0;
    que[++tail] = SS;
    while (front != tail) {
        pos = que[++front];
        for (int i = head[pos]; i != -1; i = e[i].next) {
            if (e[i].cap > 0 && dis[e[i].v] == -1) {
                dis[e[i].v] = dis[pos] + 1;    
                if (e[i].v == TT) return true;
                que[++tail] = e[i].v;
            }
        }
    }
    return false;
}

int dfs(int u, int flow) {
    if (u == TT) {
        return flow;    
    }
    int f, tf = 0;
    for (int i = head[u]; i != -1; i = e[i].next) {
        if (dis[u]+1 == dis[e[i].v] && e[i].cap > 0 && (f = dfs(e[i].v, min(e[i].cap, flow-tf)))) {
            e[i].cap -= f, e[i^1].cap += f;
            tf += f;
            if (tf == flow) return flow;
        }
    }
    if (!tf) dis[u] = -1;
    return tf;
}

int dinic() {
    int ret = 0;
    while (bfs()) {
        ret += dfs(SS, INF);    
    }    
    return ret;
}

void floyd() {
    for (int k = 1; k <= cnt; ++k) {
        for (int i = 1; i <= cnt; ++i) {
            for (int j = 1; j <= cnt; ++j) {
                R[i][j] |= R[i][k] & R[k][j];    
            }    
        }
    }    
}

int main() {
    char name[30], str[30];
    while (scanf("%d", &N) == 1) {
        cnt = 0;
        idx = -1;
        memset(rec, 0, sizeof (rec));
        memset(head, 0xff, sizeof (head));
        memset(R, 0, sizeof (R));
        mp.clear();
        for (int i = 1; i <= N; ++i) {
            scanf("%s", name);
            if (!mp.count(name)) {
                mp[name] = ++cnt;
            }
            ++rec[mp[name]]; // 将插座的信息统计好
        }
        scanf("%d", &M);
        for (int i = 1; i <= M; ++i) {
            scanf("%s %s", str, name);
            if (!mp.count(name)) {
                mp[name] = ++cnt;
            }
            addedge(SS, i, 1);
            addedge(i, CN(mp[name]), 1);
        }
        for (int i = 1; i <= cnt; ++i) {
            addedge(CN(i), MN(i), rec[i]);
            addedge(MN(i), TT, INF);
        }
        scanf("%d", &K);
        for (int i = 1; i <= K; ++i) {
            scanf("%s %s", str, name);
            if (!mp.count(str)) mp[str] = ++cnt;
            if (!mp.count(name)) mp[name] = ++cnt;
            R[mp[str]][mp[name]] = true;
        }
        floyd();
        for (int i = 1; i <= cnt; ++i) {
            for (int j = 1; j <= cnt; ++j) {
                if (R[i][j]) {
                    addedge(CN(i), CN(j), INF);
                }
            }
        }
        printf("%d\n", M-dinic());
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值