zoukankan      html  css  js  c++  java
  • UVA 753 A Plug for UNIX

    UVA_753

        我们可以把适配器看做一条有向边,而插头和插座分别看成两个点,同时引入一个源点与devices相连,引入一个汇点与receptacles相连,同时由于适配器是无限量的,所以适配器这条有向边的边权为INF,而源点与devices相连的以及receptacles和汇点相连的有向边的边权为1。

        建好图后求源点到汇点的最大流即可,然后用m减去最大流就是最终结果。

        但其实,适配器作用实际上就是将device和相应的receptacle连接起来,因此,我们可以用Floyd根据当前适配器的种类求出每个device所能够直接或间接连接的receptacle,这样我们只要用匈牙利算法求一个二分图最大匹配即可。

        (下面的程序是用网络流算法写的)

    #include<stdio.h>
    #include<string.h>
    #define MAXD 510
    #define MAXN 110
    #define MAXM 1010
    #define INF 1000000000
    char str[30], st[MAXD][30], name[MAXN][30], plug[MAXN][30];
    int N, M, K, size, e, first[MAXD], v[MAXM], next[MAXM];
    int flow[MAXM], d[MAXD], work[MAXD], q[MAXD];
    void add(int x, int y, int f)
    {
    v[e] = y;
    flow[e] = f;
    next[e] = first[x];
    first[x] = e;
    e ++;
    }
    void init()
    {
    int i, j, x, y;
    e = 0;
    size = 2;
    memset(first, -1, sizeof(first));
    scanf("%d", &N);
    for(i = 0; i < N; i ++)
    {
    scanf("%s", st[size]);
    add(size, 1, 1);
    add(1, size, 0);
    size ++;
    }
    scanf("%d", &M);
    for(i = 1; i <= M; i ++)
    scanf("%s%s", name[i], plug[i]);
    scanf("%d", &K);
    for(i = 0; i < K; i ++)
    {
    scanf("%s", str);
    for(x = 2; x < size; x ++)
    if(strcmp(str, st[x]) == 0)
    break;
    if(x == size)
    {
    strcpy(st[size], str);
    size ++;
    }
    scanf("%s", str);
    for(y = 2; y < size; y ++)
    if(strcmp(str, st[y]) == 0)
    break;
    if(y == size)
    {
    strcpy(st[size], str);
    size ++;
    }
    add(x, y, INF);
    add(y, x, 0);
    }
    for(i = 1; i <= M; i ++)
    {
    for(x = 2; x < size; x ++)
    if(strcmp(plug[i], st[x]) == 0)
    break;
    if(x != size)
    {
    add(0, size + i, 1);
    add(size + i, 0, 0);
    add(size + i, x, 1);
    add(x, size + i, 0);
    }
    }
    }
    int bfs()
    {
    int i, j, rear;
    memset(d, -1, sizeof(d));
    d[0] = 0;
    rear = 0;
    q[rear ++] = 0;
    for(i = 0; i < rear; i ++)
    for(j = first[q[i]]; j != -1; j = next[j])
    if(flow[j] && d[v[j]]== -1)
    {
    d[v[j]] = d[q[i]] + 1;
    if(v[j] == 1)
    return 1;
    q[rear ++] = v[j];
    }
    return 0;
    }
    int dfs(int cur, int a)
    {
    if(cur == 1)
    return a;
    for(int &i = work[cur]; i != -1; i = next[i])
    if(flow[i] && d[v[i]] == d[cur] + 1)
    if(int t = dfs(v[i], flow[i] < a ? flow[i] : a))
    {
    flow[i] -= t;
    flow[i ^ 1] += t;
    return t;
    }
    return 0;
    }
    int dinic()
    {
    int t, res = 0;
    while(bfs())
    {
    memcpy(work, first, sizeof(first));
    while(t = dfs(0, INF))
    res += t;
    }
    return res;
    }
    int main()
    {
    int i, T;
    scanf("%d", &T);
    for(i = 0; i < T; i ++)
    {
    init();
    if(i)
    printf("\n");
    int res = dinic();
    printf("%d\n", M - res);
    }
    return 0;
    }


  • 相关阅读:
    数据挂载
    LVS学习与测试——NAT模式
    VirtualBox 网络设置 VirtualBox中客机与主机互通
    [原]两个android程序间的相互调用(apk互调)
    [置顶] Android Service与Activity之间通信的几种方式
    [置顶] android 开发中判断网络是否连接的代码
    [置顶] 判断时间格式是否正确
    [置顶] 输出map信息
    [置顶] checkEmail判断邮箱格式
    [置顶] checkPhone判断手机号格式
  • 原文地址:https://www.cnblogs.com/staginner/p/2224055.html
Copyright © 2011-2022 走看看