C - A Plug for UNIX POJ - 1087

题意:你作为某高管去住宿了,然后宾馆里有几种插座,分别有其对应型号,你携带了几种用电器(手机,电脑一类的),也有其对应型号;可是不一定用电器就能和插座匹配上,于是宾馆的商店里提供了一些转换器,这些转换器可以将某一型号电源转换成另一型号的。问,你的用电器最少会有多少种无法充电 摘自http://www.cnblogs.com/zznulw/p/5929247.html

思路:很显然创建一个源点和一个汇点,源点指向所有的插头,所有的插座指向汇点;
显然插头与插座之间有两种方式相连
第一种:如果插头插座型号相同,可以直接将插头指向插座
第二种:如果插头与转换器的插座型号相同 ,转换器的插头与插座型号相同,那么可以插头指向转换器,转换器指向插座
还有一种情况就是转换器之间可以再转换,如果转换器1插头与转换器2的插座型号相同 ,那么两个之间可以连接。
构图之后直接网络流跑一遍,就得出结果了。

有的说转换器可以无限使用,只需将与转换器有关的边,权值改为inf就可以了

AC代码:

//#include<bits/stdc++.h>
#include<stdio.h>
#include<string.h>
#include<queue>
#include<iostream>
#define LL long long
#define Max 100005
const LL mod=1e9+7;
const LL LL_MAX=9223372036854775807;
using namespace std;
struct node{
    int v,w,next;
}edge[Max];
int head[Max],cur[Max],dis[Max],index;
int n,m,k;
int st,en;
queue<int>p;
void init()
{
    index=0;
    memset(head,-1,sizeof(head));
}
void add(int u,int v,int w){
    edge[index].v=v,edge[index].w=w;
    edge[index].next=head[u],head[u]=index++;

    edge[index].v=u,edge[index].w=0;
    edge[index].next=head[v],head[v]=index++;
}

struct d
{
    char a[30];
    int index;//保存编号
}ct[Max],cz[Max];
struct dd
{
    char to[30];//转换器插座
    char from[30];//转换器插头
    int index;//保存编号
}zhq[Max];
void add_edge()
{
    for(int i=1;i<=m;i++)//将插头与插座型号相同的连接
        for(int j=1;j<=n;j++){
            if(strcmp(ct[i].a,cz[j].a)==0){
                add(ct[i].index,cz[j].index,1);
            }
    }
    for(int i=1;i<=n;i++)//将转换器插头与插座型号相同的相连
        for(int j=1;j<=k;j++)
            if(strcmp(cz[i].a,zhq[j].from)==0){
                add(zhq[j].index,cz[i].index,1);
            }
    for(int i=1;i<=m;i++)//将插头与转换器插座型号相同的连接
        for(int j=1;j<=k;j++)
            if(strcmp(ct[i].a,zhq[j].to)==0){
                add(ct[i].index,zhq[j].index,1);
            }
    for(int i=1;i<=k;i++)//将转换器插头与转换器插座型号相同的连接
        for(int j=1;j<=k;j++)
            if(strcmp(zhq[i].from,zhq[j].to)==0){
                 add(zhq[i].index,zhq[j].index,1);
            }

    for(int i=1;i<=n;i++){//将插座连向汇点
        add(cz[i].index,n+m+k+2,1);
    }
}
bool bfs()
{
    memset(dis,0,sizeof(dis));
    while(p.size())p.pop();
    dis[st]=1;
    p.push(st);
    while(p.size()){
        int top=p.front();
        p.pop();
        for(int t=head[top];t!=-1;t=edge[t].next){
            if(dis[edge[t].v]==0 && edge[t].w>0){
                dis[edge[t].v]=dis[top]+1;
                p.push(edge[t].v);
            }
        }
    }
    return dis[en]!=0;
}
int dfs(int u,int flow){
    if(u==en)
        return flow;
    for(int& t=cur[u];t!=-1;t=edge[t].next){
        if(dis[edge[t].v]==dis[u]+1 && edge[t].w>0){
            int mn=dfs(edge[t].v,min(flow,edge[t].w));
            if(mn>0){
                edge[t].w-=mn;
                edge[t^1].w+=mn;
                return mn;
            }
        }
    }
    return 0;
}
int Dinic(){
    int ans=0,res;
    while(bfs()){
        for(int i=st;i<=en;i++)
            cur[i]=head[i];
        while(res=dfs(st,INT_MAX))
            ans+=res;
    }
    return ans;
}
int main()
{
    char t[105];
    init();
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
         scanf("%s",cz[i].a),cz[i].index=i+1;
    }
    scanf("%d",&m);
    for(int i=1;i<=m;i++){
        scanf("%s %s",t,ct[i].a),ct[i].index=i+n+1;
        add(1,i+1+n,1);//将源点与插头相连接
    }
    scanf("%d",&k);
    for(int i=1;i<=k;i++){
        scanf("%s %s",zhq[i].to,zhq[i].from);
        zhq[i].index=i+n+m+1;
    }

    add_edge();
    st=1,en=n+m+k+2;
    printf("%d\n",m-Dinic());
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值