poj1087(最大流)

传送门:A Plug for UNIX

题意:有插座用电器和适配器,用电器有插头,适配器本身有一个插孔和插头,它的作用是可以把别的插头插入到适合该适配器插孔的适配器,然后就可以用适配器的插头接到适合的插座,相当于转换插头的作用。每个插座只能插入一个插头。3种东西都最多有100个,但是任一种适配器可以有无限个。问最后最少能剩下几个用电器不能用上电。

分析:每一个用电器每一种插头看成一点,然后用电器与源点连边,插座与汇点连边,适合的插座与用电器连边,边权都为1,最后k种适配器也就是插座直接连边,边权无限大,用建好的图跑一遍dinic即可。

#pragma comment(linker,"/STACK:1024000000,1024000000")
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <limits.h>
#include <iostream>
#include <algorithm>
#include <queue>
#include <cstdlib>
#include <stack>
#include <vector>
#include <set>
#include <map>
#define LL long long
#define mod 100000000
#define inf 0x3f3f3f3f
#define eps 1e-6
#define N 510
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define PII pair<int,int>
using namespace std;
inline int read()
{
    char ch=getchar();
    int x=0,f=1;
    while(ch>‘9‘||ch<‘0‘){if(ch==‘-‘)f=-1;ch=getchar();}
    while(ch<=‘9‘&&ch>=‘0‘){x=x*10+ch-‘0‘;ch=getchar();}
    return x*f;
}
int n,m,k,vs,vt,tot;
int pre[N],q[N],cur[N],h[N];
struct edge
{
    int v,w,next;
    edge(){}
    edge(int v,int w,int next):v(v),w(w),next(next){}
}e[N*N];
void addedge(int u,int v,int w)
{
    e[tot]=edge(v,w,pre[u]);
    pre[u]=tot++;
    e[tot]=edge(u,0,pre[v]);
    pre[v]=tot++;
}
void init()
{
    memset(pre,-1,sizeof(pre));
    tot=0;
}
/*******************dinic************************/
int bfs()
{
    int head=0,tail=1;
    memset(h,-1,sizeof(h));
    q[0]=vs;h[vs]=0;
    while(head!=tail)
    {
        int u=q[head++];
        for(int i=pre[u];~i;i=e[i].next)
        {
            int v=e[i].v,w=e[i].w;
            if(w&&h[v]==-1)
            {
                h[v]=h[u]+1;
                q[tail++]=v;
            }
        }
    }
    return h[vt]!=-1;
}
int dfs(int u,int flow)
{
    if(u==vt)return flow;
    int used=0;
    for(int i=cur[u];~i;i=e[i].next)
    {
        int v=e[i].v,w=e[i].w;
        if(h[v]==h[u]+1)
        {
            w=dfs(v,min(flow-used,w));
            e[i].w-=w;e[i^1].w+=w;
            if(e[i].w)cur[u]=i;
            used+=w;
            if(used==flow)return flow;
        }
    }
    if(!used)h[u]=-1;
    return used;
}
int dinic()
{
    int res=0;
    while(bfs())
    {
        for(int i=vs;i<=vt;i++)cur[i]=pre[i];
        res+=dfs(vs,inf);
    }
    return res;
}
/********************dinic***********************/
map<string,int>mp;
char str[110][50];
char s1[50],s2[50];
void build()
{
    mp.clear();
    vs=0,vt=500;
    int num=0;
    for(int i=1;i<=n;i++)
    {
        scanf("%s",s1);
        if(!mp[s1])mp[s1]=++num;
        addedge(vs,mp[s1],1);
    }
    scanf("%d",&m);
    for(int i=1;i<=m;i++)
    {
        scanf("%s%s",s1,s2);
        if(!mp[s1])mp[s1]=++num;
        if(!mp[s2])mp[s2]=++num;
        addedge(mp[s2],mp[s1],1);
        addedge(mp[s1],vt,1);
    }
    scanf("%d",&k);
    for(int i=1;i<=k;i++)
    {
        scanf("%s%s",s1,s2);
        if(!mp[s1])mp[s1]=++num;
        if(!mp[s2])mp[s2]=++num;
        addedge(mp[s2],mp[s1],inf);
    }
}
int main()
{
    while(scanf("%d",&n)>0)
    {
        init();
        build();
        printf("%d\n",m-dinic());
    }
}

时间: 2024-11-05 18:51:04

poj1087(最大流)的相关文章

poj 1087.A Plug for UNIX 解题报告

网络流,关键在建图 建图思路在代码里 /* 最大流SAP 邻接表 思路:基本源于FF方法,给每个顶点设定层次标号,和允许弧. 优化: 1.当前弧优化(重要). 1.每找到以条增广路回退到断点(常数优化). 2.层次出现断层,无法得到新流(重要). 时间复杂度(m*n^2) */ #include <iostream> #include <cstdio> #include <cstring> #include <map> #define ms(a,b) mem

POJ1087:A Plug for UNIX(最大流)

A Plug for UNIX 题目链接:https://vjudge.net/problem/POJ-1087 Description: You are in charge of setting up the press room for the inaugural meeting of the United Nations Internet eXecutive (UNIX), which has an international mandate to make the free flow o

poj1087 网络最大流

http://poj.org/problem?id=1087 Description You are in charge of setting up the press room for the inaugural meeting of the United Nations Internet eXecutive (UNIX), which has an international mandate to make the free flow of information and ideas on

poj1087 A Plug for UNIX(网络流最大流)

http://poj.org/problem?id=1087 好久没遇见过这么坑的题了这个题真是挫的够可以的.题目大意:你作为某高管去住宿了,然后宾馆里有几种插座,分别有其对应型号,你携带了几种用电器(手机,电脑一类的), 也有其对应型号:可是不一定用电器就能和插座匹配上,于是宾馆的商店里提供了一些转换器,这些转换器可以将某一型号电源转换成另一型号的.问,你的用电器最少会有多少种无 法充电.也就是问可以用上电的用电器的最大数目,之后用电器总数减去此可用电最大数目即可得到最小不能用电数目. 一开始

ZOJ1157, POJ1087,UVA 753 A Plug for UNIX (最大流)

链接 : http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=26746 题目意思有点儿难描述 用一个别人描述好的. 我的建图方法:一个源点一个汇点,和所有种类的插座.输入的n个插座直接与源点相连,容量为1,m个物品输入里 记录每个插座对应的物品个数,物品数然后大于0的插座直接连到汇点,意味着最终的物品只能由这些插座流出.中间的插座转换容量都是INF  a b表示  无论多少b都可以选择转化到a. /*-------------

POJ1087 A Plug for UNIX 【最大流】

A Plug for UNIX Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 13855   Accepted: 4635 Description You are in charge of setting up the press room for the inaugural meeting of the United Nations Internet eXecutive (UNIX), which has an int

poj1087最小割

最大流最小割定理:移除最小边集使网络流中断的集值等于这个网络的最大流. 建图: 第一个cpu 流向第i的 模块的流量为ai  ,  第i个模块流向 第二个cpu的流量为 bi  .模块之间连边 a->b= w   b->a=w. #include <cstdio> #include <cstring> #include <algorithm> #include <climits> #include <string> #include

对IO流的操作(文件大小,拷贝,移动,删除)

import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.FileReader;import java.io.FileWriter;import java.io.IOException;import java.io.SequenceInputStream; class LjyFileClass { /*LjyFileClass工具类使用需知: * * 1.计算

hdu3461Marriage Match IV 最短路+最大流

//给一个图.给定起点和终点,仅仅能走图上的最短路 //问最多有多少种走的方法.每条路仅仅能走一次 //仅仅要将在最短路上的全部边的权值改为1.求一个最大流即可 #include<cstdio> #include<cstring> #include<iostream> #include<queue> #include<vector> using namespace std ; const int inf = 0x3f3f3f3f ; const